Jack
Jack

Reputation: 3057

Pythonic way of sorting a list

For example i would have a list of of

lists = ['jack 20', 'ben 10', 'alisdar 50', 'ollie 35']

and I would need to sort it so based on the number,

lists.sort() = ['ben 10', 'jack 20', 'ollie 35', 'alisdar 50']

Possible somehow use formatting with split()?

Upvotes: 3

Views: 147

Answers (3)

hughdbrown
hughdbrown

Reputation: 49003

It would be better if you had a more appropriate data type than a string to represent, say, a person's name and age. One way would be a dictionary:

lists = ['jack 20', 'ben 10', 'alisdar 50', 'ollie 35']
d = dict(item.split(' ') for item in lists)

This constructs a dictionary from a stream of two-element lists.

Then you can sort like this:

print sorted((v, k) for k, v in d.iteritems())

and get this:

>>> lists = ['jack 20', 'ben 10', 'alisdar 50', 'ollie 35']
>>> d = dict(item.split(' ') for item in lists)
>>> print sorted((v, k) for k, v in d.iteritems())
[('10', 'ben'), ('20', 'jack'), ('35', 'ollie'), ('50', 'alisdar')]

Or you could convert age to integer:

>>> lists = ['jack 20', 'ben 10', 'alisdar 50', 'ollie 35']
>>> person_iter = (item.split(' ') for item in lists)
>>> d = {k: int(v) for k, v in person_iter}
>>> print sorted((v, k) for k, v in d.iteritems())
[(10, 'ben'), (20, 'jack'), (35, 'ollie'), (50, 'alisdar')]

person_iter is a generator that produces pairs of name-age. You feed that to the dictionary comprehension and convert the second argument to an integer.

The basic idea, though, is that you will have an easier time if you use more precise data types for your purposes.

Upvotes: 1

Martijn Pieters
Martijn Pieters

Reputation: 1121356

Use a key function:

lists.sort(key=lambda s: int(s.rsplit(None, 1)[-1]))

The key callable is passed each and every element in lists and that element is sorted according to the return value. In this case we

  • split once on whitespace, starting on the right
  • take the last element of the split
  • turn that into an integer

The argument to key can be any callable, but a lambda is just more compact. You can try it out in the command prompt:

>>> key_function = lambda s: int(s.rsplit(None, 1)[-1])
>>> key_function('ben 10')
10
>>> key_function('Guido van Rossum 42')
42

In effect, when sorting the values are augmented with the return value of that function, and what is sorted is:

[(20, 0, 'jack 20'), (10, 1, 'ben 10'), (50, 2, 'alisdar 50'), (35, 3, 'ollie 35')]

instead (with the second value, the index of the element, added to keep the original order in case of equal sort keys).

Result:

>>> lists = ['jack 20', 'ben 10', 'alisdar 50', 'ollie 35']
>>> lists.sort(key=lambda s: int(s.rsplit(None, 1)[-1]))
>>> lists
['ben 10', 'jack 20', 'ollie 35', 'alisdar 50']

Upvotes: 13

Pavel Anossov
Pavel Anossov

Reputation: 62868

Use a key function that does what you want:

lists.sort(key=lambda e: int(e.split()[1]))

If some of your items don't follow that format, you'll have to write something a little more elaborate.

Upvotes: 3

Related Questions