Python 用 lambda 修改元组

Python modify tuple with lambda

我有一个如下所示的元组:

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

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

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

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

所以我想在一行中表达的是:

在状态下将 pair[1] 设置为 True,其中 pair[0] = (givenX, givenY)

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

更新:

谢谢大家的回答。这是我最后所做的:

state = dict(state)

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

state = tuple(state.items())

由于 bool 是不可变的(毕竟它们是普通整数),您必须重建元组才能修改它们:

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),)

显然,您不能就地修改元组,但可以使用生成器表达式创建一个新元组:

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))

听起来您已经到了将数据封装在一组 类 中的好主意。

您可以使用 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