Comparing all elements of two tuples (with all() functionality)

So i know that comparisons on tuples work lexicographically:

Tuples and lists are compared lexicographically using comparison of corresponding elements. This means that to compare equal, each element must compare equal and the two sequences must be of the same type and have the same length.

If not equal, the sequences are ordered the same as their first differing elements. For example, cmp([1,2,x], [1,2,y]) returns the same as cmp(x,y). If the corresponding element does not exist, the shorter sequence is ordered first (for example, [1,2] < [1,2,3]).

So from this:

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

But i want to compare all elements of 2 tuples in order, so functionally i want something akin to (using values from above):

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

As an example in practice, for something like screen coordinates, if you wanted to check if something was 'inside' the screen at (0,0), but done a comparison like coord > (0,0), if the x coord was bigger than 0, but the y coord was smaller it would still return true, which isn't what is needed in this case.

As sort of a sub question/discussion:
I am not sure why comparing 2 tuples of different values is returned in such a way. You are not given any sort of index, so the only thing you get from comparing a tuple (that isn't testing equality) is that at some point in the tuple, one of the comparisons will throw a true or false value when they are not equal. How could you take advantage of that?


You can achieve this with a list comprehension and the zip built-in:

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

You can use all() or any() on the returned list.


用第二个代码示例中的tuple(i > j for i, j in zip(a,b))替换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

You might consider using the following vectorized approach , which is usually more performant, and syntactically/semantically very clear:

>>> 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 is quite performant, and the resulting objects above also embed the any()/all() query methods you want. If you will be performing vector-like operations (as your screen coordinates example suggests), you may consider working with 'a' and 'b' as numpy arrays, instead of tuples. That results in the most efficient implementation of what you seek: no pre-conversion necessary, and Python-based loops are replaced with efficient numpy-based loops. This is worth highlighting because there are two and potentially three loops involved: (1) a preprocessing loop during conversion (which you can eliminate); (2) an item-by-item comparison loop; and (3) a query loop to answer the any/all question.

  • Note that I could've also created a numpy array from 'b', but not doing so eliminated one conversion step and pre-processing time . Since that approach results in one operand being a numpy array and the other a tuple , as the sequences grow, that may/may-not result in less speedy item-by-item comparisons (which strict numpy-to-numpy is good at). Try it. :)

  • 链接地址: http://www.djcxy.com/p/53588.html

    上一篇: Python中的元组比较

    下一篇: 比较两个元组的所有元素(具有all()功能)