Python使用lambda修改元组



我有一个元组,看起来如下:

(((1, 1), False), ((1, top), False), ((right, 1), False), ((right, top), False))

因此,元组中有4个元组,每个元组存储一个坐标(另一个元组)和一个布尔。

(我不使用dict或list,因为我需要它是可哈希的)

有没有一种聪明的方法可以将给定坐标的布尔值更改为true?

所以我想用一句话表达的是:

状态中设置对[1]为True,其中对[0]=(givenX,givenY)

有没有一种聪明的方法可以在python中做到这一点?

更新:

谢谢你的回答。以下是我最终所做的:

state = dict(state)
if (givenX, givenY) in state.keys():
    state[(givenX, givenY)] = True
state = tuple(state.items())

由于bool s是不可变的(毕竟它们是纯整数),因此必须重构元组才能修改它们:

tuple(x if x[0] != (givenX, givenY) else (x[0], True) for x in your_tuple)

尽管我认为最简单的方法是使用dict,并在进行必要的修改后将其转换为tuple

In [23]: d = {(1, 2): False}
In [24]: d[1, 2] = True
In [25]: tuple(d.items())
Out[25]: (((1, 2), True),)

听起来,将数据封装在一组类中是个好主意。

您可以使用collections.namedtuple作为类的基础,它将创建不可变的对象,为这些对象创建一个或多个不同值的新实例很容易。您甚至可以对创建的命名元组进行子类化,并添加自己的方法,这将有助于轻松替换对象中的值,同时保持代码简洁可读。例如

from collections import namedtuple
right = "right"
top = "top"
tuple_data = (((1, 1), False), ((1, top), False), ((right, 1), False), ((right, top), False))
# create a subclass of tuple whose name is the first argument, and the second argument 
# is space separated fields which are aliases for accessing the class as a tuple.
# eg. Point(1, 2).x == Point(1, 2)[0]
Point = namedtuple("Point", "x y")
_PointValueBase = namedtuple("PointValue", "point value")
_RectangleBase = namedtuple("Rectangle", "leftbottom lefttop rightbottom righttop")
class PointValue(_PointValueBase):
    def replace_if_point_equal(self, point, value):
        if self.point == point:
            return self._replace(value=value)
        return self
class Rectangle(_RectangleBase):
    def replace(self, point, value):
        return Rectangle._make(pv.replace_if_point_equal(point, value) for pv in self)
# convert tuple_data to a Rectangle
rect = Rectangle(*(PointValue(Point(*p), v) for p, v in tuple_data))
print(rect) # nice textual representation
assert eval(str(rect)) == rect # which is also machine readable
assert isinstance(rect, tuple) # is a subclass of tuple
assert hash(tuple_data) == hash(rect) # so its hash is the same
given_point = Point(x=right, y=top)
new_rect = rect.replace(given_point, value=True)
print(new_rect)
assert new_rect.righttop.value is True

显然,您不能在适当的位置修改元组,但您可以使用生成器表达式创建一个新的元组:

given = (givenX, givenY)
result = tuple((p, p==given) for p, _ in original_tuple)

如果您已经将一些值设置为True,并希望保持它们的样子:

result = tuple((p1, p2 or p1==given) for p1, p2 in original_tuple)

是的,您可以使用lambda函数来完成此操作。

right = 5 # dummy value
top = 7 # dummy value
search = (1,7) # needle coordinates
tups = (((1, 1), False), ((1, top), False), ((right, 1), False), ((right, top), False))
print map(lambda x: (x[0], not x[1]) if x[0]==search else (x[0], x[1]), tups)
# [((1, 1), False), ((1, 7), True), ((5, 1), False), ((5, 7), False)]

然而,这将导致元组列表,因此您需要再次将其转换为元组

print tuple(map(lambda x: (x[0], not x[1]) if x[0]==search else (x[0], x[1]), tups))
# (((1, 1), False), ((1, 7), True), ((5, 1), False), ((5, 7), False))

最新更新