2

Let's say I have such a list:

['word_4_0_w_7', 'word_4_0_w_6', 'word_3_0_w_10', 'word_3_0_w_2'] 

and I want to sort them according to number that comes after "word" and according to number after "w". It will look like this:

 ['word_3_0_w_2', 'word_3_0_w_10', 'word_4_0_w_6', 'word_4_0_w_7'] 

What comes in mind is to create a bunch of list and according to index after "word" stuff them with sorted strings according "w", and then merge them.

Is in Python more clever way to do it?

1
  • 2
    sorted(words, key=lambda word: (int(word[5]), int(word[11:])) Commented Nov 13, 2015 at 13:11

3 Answers 3

3

Use Python's key functionality, in conjunction with other answers:

def mykey(value): ls = value.split("_") return int(ls[1]), int(ls[-1]) newlist = sorted(firstlist, key=mykey) ## or, if you want it in place: firstlist.sort(key=mykey) 

Python will be more efficient with key vs cmp.

Sign up to request clarification or add additional context in comments.

Comments

1

You can provide a function to the sort() method of list objects:

l = ['word_4_0_w_7', 'word_4_0_w_6', 'word_3_0_w_10', 'word_3_0_w_2'] def my_key_func(x): xx = x.split("_") return (int(xx[1]), int(xx[-1])) l.sort(key=my_key_func) 

Output:

print l ['word_3_0_w_2', 'word_3_0_w_10', 'word_4_0_w_6', 'word_4_0_w_7'] 

edit: Changed code according to comment by @dwanderson ; more info on this can be found here.

1 Comment

I think it's recommended to use the key functionality, rather than the cmp, since sorting will calculate the key O(n) times but can do O(n**2) cmps (I think). Simple change would just be: def key(x): xx = x.split("_"); return int(xx[1]), int(xx[-1]) and then l.sort(key=mykey). The output will be the same, but it's more efficient, and the preferred Python way.
1

You can use a function to extract the relevant parts of your string and then use those parts to sort:

a = ['word_4_0_w_7', 'word_4_0_w_6', 'word_3_0_w_10', 'word_3_0_w_2'] def sort_func(x): parts = x.split('_'); sort_key = parts[1]+parts[2]+"%02d"%int(parts[4]) return sort_key a_sorted = sorted(a,key=sort_func) 

The expression "%02d" %int(x.split('_')[4]) is used to add a leading zero in front of second number otherwise 10 will sort before 2. You may have to do the same with the number extracted by x.split('_')[2].

4 Comments

While lambda's are great for one-offs, and this does seem like a pretty simple one, I'd say the expression is just complex enough that an inline lambda like that is unreadable/unmaintainable. Way too easy to make a formatting mistake, and the next person who comes along and looks at the code will have to spend a few minutes teasing out what it means and if it's correct
I have refactored the code so the lambda is defined on a separate line. You can now call it to test if it works.
Why not just make it a two or three line function then? My whole point was that it's hard to read/maintain. Assigning the lambda to a function, instead of using a function proper, seems even less readable, since it would probably cause every Python programmer to pause and ask "Now why did they bother to do assign the lambda instead of just making a normal function?"
I changed as Guido van Rossum doesn't seem to like lambda operators either, see stackoverflow.com/questions/134626/…

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.