Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can I sort text by its numeric value in Python?

I have dict in Python with keys of the following form:

mydict = {'0'     : 10,
          '1'     : 23,
          '2.0'   : 321,
          '2.1'   : 3231,
          '3'     : 3,
          '4.0.0' : 1,
          '4.0.1' : 10,
          '5'     : 11,
          # ... etc
          '10'    : 32,
          '11.0'  : 3,
          '11.1'  : 243,
          '12.0'  : 3,
          '12.1.0': 1,
          '12.1.1': 2,
          }

Some of the indices have no sub-values, some have one level of sub-values and some have two. If I only had one sub-level I could treat them all as numbers and sort numerically. The second sub-level forces me to handle them all as strings. However, if I sort them like strings I'll have 10 following 1 and 20 following 2.

How can I sort the indices correctly?

Note: What I really want to do is print out the dict sorted by index. If there's a better way to do it than sorting it somehow that's fine with me.

like image 636
Nathan Fellman Avatar asked Oct 07 '09 22:10

Nathan Fellman


People also ask

How do you sort a string by a number in Python?

To do this we can use the extra parameter that sort() uses. This is a function that is called to calculate the key from the entry in the list. We use regex to extract the number from the string and sort on both text and number.

How do you sort numbers and letters in Python?

Use the Python List sort() method to sort a list in place. The sort() method sorts the string elements in alphabetical order and sorts the numeric elements from smallest to largest. Use the sort(reverse=True) to reverse the default sort order.

Can you sort a list which contains both numeric and string data?

You can use natsort.

How do you sort numeric?

In first, select the data and then click on the Sort option from the Data menu tab. Choose the column whose value we want to sort, then choose Sort on Value from the drop-down. Now we can Sort the number by Largest to Smallest and vice-versa.


3 Answers

You can sort the keys the way that you want, by splitting them on '.' and then converting each of the components into an integer, like this:

sorted(mydict.keys(), key=lambda a:map(int,a.split('.')))

which returns this:

['0',
 '1',
 '2.0',
 '2.1',
 '3',
 '4.0.0',
 '4.0.1',
 '5',
 '10',
 '11.0',
 '11.1',
 '12.0',
 '12.1.0',
 '12.1.1']

You can iterate over that list of keys, and pull the values out of your dictionary as needed.

You could also sort the result of mydict.items(), very similarly:

sorted(mydict.items(), key=lambda a:map(int,a[0].split('.')))

This gives you a sorted list of (key, value) pairs, like this:

[('0', 10),
 ('1', 23),
 ('2.0', 321),
 ('2.1', 3231),
 ('3', 3),
 # ...
 ('12.1.1', 2)]
like image 87
Ian Clelland Avatar answered Oct 06 '22 09:10

Ian Clelland


Python's sorting functions can take a custom compare function, so you just need to define a function that compares keys the way you like:

def version_cmp(a, b):
  '''These keys just look like version numbers to me....'''
  ai = map(int, a.split('.'))
  bi = map(int, b.split('.'))
  return cmp(ai, bi)

for k in sorted(mydict.keys(), version_cmp):
  print k, mydict[k]

In this case you should better to use the key parameter to sorted(), though. See Ian Clelland's answer for an example for that.

like image 20
sth Avatar answered Oct 06 '22 09:10

sth


As an addendum to Ian Clelland's answer, the map() call can be replaced with a list comprehension... if you prefer that style. It may also be more efficient (though negligibly in this case I suspect).

sorted(mydict.keys(), key=lambda a: [int(i) for i in a.split('.')])

like image 20
Rob Cowie Avatar answered Oct 06 '22 09:10

Rob Cowie