I have a list of tuples that looks something like this:
[('abc', 121),('abc', 231),('abc', 148), ('abc',221)]
I want to sort this list in ascending order by the integer value inside the tuples. Is it possible?
I have a list of tuples that looks something like this:
[('abc', 121),('abc', 231),('abc', 148), ('abc',221)]
I want to sort this list in ascending order by the integer value inside the tuples. Is it possible?
Try using the key
keyword argument of sorted()
, which sorts in increasing order by default:
sorted(
[('abc', 121), ('abc', 231), ('abc', 148), ('abc', 221)],
key=lambda x: x[1]
)
key
should be a function that identifies how to retrieve the comparable element from your data structure. In your case, it is the second element of the tuple, so we access [1]
.
For optimization, see jamylak's response using operator.itemgetter(1)
, which is essentially a faster version of lambda x: x[1]
.
sorted(some_list, lambda x: (x[0], -x[1],))
–
Laryssa >>> from operator import itemgetter
>>> data = [('abc', 121),('abc', 231),('abc', 148), ('abc',221)]
>>> sorted(data,key=itemgetter(1))
[('abc', 121), ('abc', 148), ('abc', 221), ('abc', 231)]
IMO using itemgetter
is more readable in this case than the solution by @cheeken. It is
also faster since almost all of the computation will be done on the c
side (no pun intended) rather than through the use of lambda
.
>python -m timeit -s "from operator import itemgetter; data = [('abc', 121),('abc', 231),('abc', 148), ('abc',221)]" "sorted(data,key=itemgetter(1))"
1000000 loops, best of 3: 1.22 usec per loop
>python -m timeit -s "data = [('abc', 121),('abc', 231),('abc', 148), ('abc',221)]" "sorted(data,key=lambda x: x[1])"
1000000 loops, best of 3: 1.4 usec per loop
itemgetter()
is a better solution. However, I thought a lambda expression would make it clearer how key
functions. –
Kiri time `python -c "the code"`
then I got 'human-eye' results that you spell out, as well as sys clock times that were faster. Still not sure why this is, but it was reproducible. I gather it has something to do with the overhead of loading in the module's, but still does not quite make since to me, just yet. –
Confectioner python -m timeit -s
but yea I think you are on point to say that in a production scenario you only pay that lib load penalty once. and... as for who cares about that microsecond... you care because the assumption is that your sorting data is going to get quite large and that microsecond is going to turn into real seconds once the data set grows. –
Confectioner sorted(x)
will give you desired order. So, that, probably with a comment would be the most pythonic statement. –
Sartor data
to 48 elements and do it in Jupyter. The results are 5.19 µs ± 42.6 ns per loop
for %timeit sorted(data, key=itemgetter(1))
and 6.7 µs ± 63.6 ns per loop
for %timeit sorted(data, key=lambda x: x[1])
. So itemgetter
is still faster. –
Abysm Adding to Cheeken's answer, This is how you sort a list of tuples by the 2nd item in descending order.
sorted([('abc', 121),('abc', 231),('abc', 148), ('abc',221)],key=lambda x: x[1], reverse=True)
sorted
function just produce a new list which is sorted for you. –
Oxidase As a python neophyte, I just wanted to mention that if the data did actually look like this:
data = [('abc', 121),('abc', 231),('abc', 148), ('abc',221)]
then sorted()
would automatically sort by the second element in the tuple, as the first elements are all identical.
For an in-place sort, use
foo = [(list of tuples)]
foo.sort(key=lambda x:x[0]) #To sort by first element of the tuple
From python wiki:
>>> from operator import itemgetter, attrgetter
>>> sorted(student_tuples, key=itemgetter(2))
[('dave', 'B', 10), ('jane', 'B', 12), ('john', 'A', 15)]
>>> sorted(student_objects, key=attrgetter('age'))
[('dave', 'B', 10), ('jane', 'B', 12), ('john', 'A', 15)]
For a lambda-avoiding method, first define your own function:
def MyFn(a):
return a[1]
then:
sorted([('abc', 121),('abc', 231),('abc', 148), ('abc',221)], key=MyFn)
lambda x: x[1]
in multiple areas of code. –
Bahrain For Python 2.7+
, this works which makes the accepted answer slightly more readable:
sorted([('abc', 121),('abc', 231),('abc', 148), ('abc',221)], key=lambda (k, val): val)
The fact that the sort values in the OP are integers isn't relevant to the question per se. In other words, the accepted answer would work if the sort value was text. I bring this up to also point out that the sort can be modified during the sort (for example, to account for upper and lower case).
>>> sorted([(121, 'abc'), (231, 'def'), (148, 'ABC'), (221, 'DEF')], key=lambda x: x[1])
[(148, 'ABC'), (221, 'DEF'), (121, 'abc'), (231, 'def')]
>>> sorted([(121, 'abc'), (231, 'def'), (148, 'ABC'), (221, 'DEF')], key=lambda x: str.lower(x[1]))
[(121, 'abc'), (148, 'ABC'), (231, 'def'), (221, 'DEF')]
© 2022 - 2024 — McMap. All rights reserved.