【问题标题】:Python modify tuple with lambdaPython 使用 lambda 修改元组
【发布时间】:2015-02-22 21:35:35
【问题描述】:

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

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

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

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

对于给定的坐标,是否有一种聪明的方法可以将 bool 更改为 true?

所以我想在一个班轮中表达的是:

在状态集 pair[1] 为 True where pair[0] = (givenX, givenY)

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

更新:

感谢您的所有回答。这是我最后所做的:

state = dict(state)

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

state = tuple(state.items())

【问题讨论】:

  • In state set pair[1] to True where pair[0] = (givenX, givenY) 是什么意思?
  • @AvinashRaj 这对我来说听起来很清楚。如果索引 0 (pair[0]) 处的值是 (givenX, givenY),则将索引 1 (pair[1]) 处的元组值设置为 True
  • @MarkusMeskanen,谢谢
  • 您可能想查看lenses library

标签: python lambda tuples


【解决方案1】:

由于bools 是不可变的(毕竟它们是纯整数),您必须重构您的元组来修改它们:

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

【讨论】:

  • 虽然这个答案可能是最好的解决方案,但它不符合 OP 的问题。他要求用 lambda 做这个,所以我真的不明白他为什么接受这个答案。此外,此答案仅适用于将布尔值从 false 设置为 true,而不是相反。
  • @kasperTaeymans 我认为他们说得很清楚 - “将 pair[1] 设置为 True
【解决方案2】:

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

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

【讨论】:

    【解决方案3】:

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

    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)
    

    【讨论】:

      【解决方案4】:

      是的,您可以使用 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))
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2020-07-04
        • 1970-01-01
        • 2013-06-06
        • 2011-11-13
        • 1970-01-01
        • 2021-12-16
        • 2021-03-21
        相关资源
        最近更新 更多