Reputation: 5074
I was fiddling around with lists of tuples and I was wondering, what would be the fastest way to grab the greatest 1st and 2nd values from the list of tuples simultaneously? For example assume we have a list of tuples like so:
_list = [(0, 3), (2, 1), (3, 2), (2, 4)]
The max first value is 3 and the max second value is 4, therefore I would like to get the tuple (3, 4)
. What might be the fastest way to do this?
Upvotes: 1
Views: 72
Reputation: 7821
After timing the various scripts posted here (with list length of 10000), the fastest version is a traditional for loop:
mi = mj = float('-inf')
for i, j in lst:
if i > mi:
mi = i
if j > mj:
mj = j
print mi, mj
But the prettiest has to be by using zip:
lst = [(0, 3), (2, 1), (3, 2), (2, 4)]
print tuple(max(x) for x in zip(*lst))
# -> (3, 4)
Timings (on Python 2.7.1):
Function Time Performance
max_for2(lst): 0.9241 100%
max_izip(lst): 1.3093 141%
max_for1(lst): 1.3596 147%
max_zip(lst): 1.4750 159%
max_gen(lst): 2.1235 229%
Timing code:
setup = '''
from itertools import izip
from random import randint
def max_zip(lst):
return tuple(max(x) for x in zip(*lst))
def max_izip(lst):
return tuple(max(x) for x in izip(*lst))
def max_gen(lst):
return max(a[0] for a in lst), max(a[1] for a in lst)
def max_for1(lst):
mi = mj = float('-inf')
for i, j in lst:
mi = i if i > mi else mi
mj = j if j > mj else mj
return mi, mj
def max_for2(lst):
mi = mj = float('-inf')
for i, j in lst:
if i > mi:
mi = i
if j > mj:
mj = j
return mi, mj
lst = [(randint(0, 10000), randint(0, 10000)) for _ in xrange(10000)]
'''
from timeit import timeit
statements= (
'max_zip(lst)',
'max_izip(lst)',
'max_gen(lst)',
'max_for1(lst)',
'max_for2(lst)'
)
timings = {}
for stmt in statements:
timings[stmt] = timeit(stmt=stmt, setup=setup, number=1000)
print 'Function\t\tTime\tPerformance'
for key, value in sorted(timings.iteritems(), key=lambda x: x[1]):
print '{}:\t{:.4f}\t{}%'.format(
key, value, int(100*value/min(timings.values())))
Upvotes: 4
Reputation: 4521
Simply do like this. :)
max(lst)[0], max(lst, key=lambda x:x[1])[1]
Time:
>>> %timeit max(lst)[0],max(lst, key=lambda x:x[1])[1]
1000000 loops, best of 3: 1.32 us per loop
#http://stackoverflow.com/a/23023689/2931409
>>> %timeit (max(a[0] for a in lst), max(a[1] for a in lst))
1000000 loops, best of 3: 1.41 us per loop
#http://stackoverflow.com/a/23023736/2931409
>>> %timeit tuple(max(x) for x in itertools.izip(*lst))
1000000 loops, best of 3: 1.73 us per loop
Upvotes: 0
Reputation: 8325
This would do the trick:
(max(a[0] for a in list), max(a[1] for a in list))
Upvotes: 1
Reputation: 19264
>>> mx = []
>>> mn = []
>>> for i, j in _list:
... mx.append(i)
... mn.append(j)
...
>>> x = (max(mx), max(mn))
>>> x
(3, 4)
Append each value to a list, and then get the maximum. From that, create a tuple.
Upvotes: 1