【问题标题】:Comparing all elements of two tuples (with all() functionality)比较两个元组的所有元素(具有 all() 功能)
【发布时间】:2012-05-08 17:18:46
【问题描述】:

所以我知道comparisons on tuples 按字典顺序工作:

元组和列表使用对应元素的比较来按字典顺序进行比较。这意味着要比较相等,每个元素必须比较相等,并且两个序列必须是相同的类型并且具有相同的长度。

如果不相等,则序列的排序与其第一个不同的元素相同。例如, cmp([1,2,x], [1,2,y]) 返回与 cmp(x,y) 相同的结果。如果对应的元素不存在,则先排序较短的序列(例如,[1,2]

所以从这里:

>>> a = (100, 0)
>>> b = (50, 50)
>>> a > b
True

但我想按顺序比较 2 个元组的所有元素,所以在功能上我想要类似于(使用上面的值):

>>> a > b
(True, False) #returned tuple containing each comparison
>>> all(a > b)
False

作为实践中的一个例子,对于像屏幕坐标这样的东西,如果你想检查某个东西是否在屏幕的“内部”(0,0),但是做了一个比较像 coord > (0,0),如果x 坐标大于 0,但 y 坐标更小它仍然会返回 true,这不是本例所需要的。

作为一个子问题/讨论:
我不确定为什么以这种方式返回比较 2 个不同值的元组。您没有得到任何类型的索引,因此您从比较元组(不是测试相等性)中得到的唯一结果是,在元组中的某个点,其中一个比较会在它们是时抛出真值或假值不相等。你怎么能利用它?

【问题讨论】:

  • 元组比较的一个有用情况是版本号; (3, 1, 4, 2) < (3, 2, 0, 1) 之类的

标签: python comparison tuples language-design


【解决方案1】:

我觉得答案中缺少使用 map 和 lambda 函数

>>> a = (100, 0)
>>> b = (50, 50)
>>> all(map(lambda x,y: x > y, a, b))
False

【讨论】:

    【解决方案2】:

    您可以考虑使用以下矢量化方法,它通常性能更高,并且在语法/语义上非常清晰:

    >>> import numpy
    >>>
    >>> a = (100, 0)
    >>> b = (50, 50)
    >>> numpy.array(a) > b
    array([ True, False], dtype=bool)
    >>> 
    >>> (numpy.array(a) > b).any()
    True
    >>> (numpy.array(a) > b).all()
    False
    
    • numpy 的性能非常好,上面生成的对象还嵌入了您想要的 any()/all() 查询方法。如果您将执行类似矢量的操作(如 屏幕坐标 示例所示),您可以考虑将 'a' 和 'b' 作为 numpy 数组,而不是元组。这会导致您所寻求的最有效的实现:不需要预转换,并且基于 Python 的循环被高效的基于 numpy 的循环所取代。这是值得强调的,因为涉及两个甚至三个可能的循环:(1)转换期间的预处理循环(您可以消除); (2)逐项比较循环; (3) 一个查询循环来回答任何/所有问题。

    • 请注意,我也可以从“b”创建一个 numpy 数组,但不这样做会消除一个转换步骤和 预处理时间。由于这种方法导致一个操作数是 numpy 数组,而另一个操作数是 tuple,随着序列的增长,这可能会/可能不会导致逐项速度降低项目比较(严格的 numpy-to-numpy 擅长)。试试吧。 :)

    【讨论】:

      【解决方案3】:

      要获得所描述的行为,请尝试:

      [ai > bi for ai,bi in zip(a,b)]
      

      以这种方式返回元组比较的原因是您可能想要编写如下内容:

      if a >= (0.,0.):
          print "a has only positive values"
      else:
          print "a has at least one negative value"
      

      如果 Python 要返回您描述的元组,那么 else 将永远不会发生。试试

      if (False,False):
          print "True!" # This is what is printed.
      else:
          print "False!"
      

      我希望这会有所帮助。

      【讨论】:

        【解决方案4】:

        在您的第二个代码示例中将 a > b 替换为 tuple(i > j for i, j in zip(a,b))

        >>> a = (100, 0)
        >>> b = (50, 50)
        >>> tuple(i > j for i, j in zip(a,b))
        (True, False)
        >>> all(i > j for i, j in zip(a,b))
        False
        

        【讨论】:

          【解决方案5】:

          您可以通过列表理解和内置 zip 来实现这一点:

          >>> a = (100, 0)
          >>> b = (50, 50)
          >>> [(a > b) for a, b in zip(a,b)]
          [True, False]
          

          您可以在返回的列表上使用 all() 或 any()。

          【讨论】:

          • 如果您调用allany,那么您不再需要列表解析,但可以使用生成器,由于特殊的语法规则,它允许您删除额外的括号对.
          猜你喜欢
          • 1970-01-01
          • 2011-01-13
          • 2016-01-25
          • 1970-01-01
          • 2019-10-10
          • 2016-06-19
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多