9

I am new to python and hoping that someone can help me out with this. I need to sort a list of strings :

s = ['status', 'value', 'place', 'tag']

I need to sort in such a way that the sorted list looks like this :

s_sorted = ['tag', 'place', 'status', 'value']

In order words, the specific string 'tag' needs to be always in front and the rest of the strings are going to be sorted. I was trying to come up with a comparator that will allow me to do so. But I haven't been able to do that so far. If anyone has experience solving problem like this, I would appreciate if you can share some thoughts.

Ashwini Chaudhary
  • 244,495
  • 58
  • 464
  • 504
Santanu C
  • 1,362
  • 3
  • 20
  • 38

3 Answers3

13
s = ['status', 'value', 'place', 'tag']
s_sorted = sorted(s, key=lambda x:(x!='tag', x))

The key generates a tuple, with first element boolean of if the element isn't 'tag'. sort sorts by the first element, then the second. This way tag always comes first because False sorts before True.

In the case of the remaining elements - not equal to 'tag' - sorting is done normally on the second tuple element, which is a lexicographical string sort on the value itself.


From the sorted documentation:

key specifies a function of one argument that is used to extract a comparison key from each list element: key=str.lower. The default value is None (compare the elements directly).

Boris Verkhovskiy
  • 14,854
  • 11
  • 100
  • 103
mhlester
  • 22,781
  • 10
  • 52
  • 75
  • Where is the documentation on how passing `key` a tuple works? I can't find it. – Two-Bit Alchemist Apr 15 '14 at 17:43
  • Where in that does it say that if the `key` function returns a tuple it will compare first by the first element, then by the second, and so on? Or is that not what it is doing? – Two-Bit Alchemist Apr 15 '14 at 19:08
  • @Two-BitAlchemist It might not be mentioned there, but the value returned by key is used for comparison and in general that's how tuple/list comparison works. – Ashwini Chaudhary Apr 15 '14 at 19:10
  • 1
    Yes, that is what's going on. It's how tuples sort. Similar to how sorting strings sorts first by the first character, then by the second character, and so on. Same mechanism. Here's another post about it: [How does Python sort a list of tuples?](http://stackoverflow.com/questions/644170/how-does-python-sort-a-list-of-tuples) The key function is returning a tuple for purposes of sorting – mhlester Apr 15 '14 at 19:11
  • That's pretty clever. – Boris Verkhovskiy Apr 24 '20 at 15:04
5

You can do something like this:

>>> s = ['status', 'value', 'place', 'tag']
>>> s.sort(key=lambda x: (x != 'tag', x))
>>> s
['tag', 'place', 'status', 'value']

Here are going to compare tuples containing a boolean and the item itself, for 'tag' the boolean value is going to be False, so it will always be at the front. Rest of the values will have the boolean value as True, and True > False in Python.

Ashwini Chaudhary
  • 244,495
  • 58
  • 464
  • 504
1

How about the simple approach?

first_item = 'tag'
s.pop(s.index(first_item))
s.sort()
s.insert(0, first_item)

Assuming that the first_item only appears once in the target list, the above would work.

Burhan Khalid
  • 169,990
  • 18
  • 245
  • 284
  • If there are more than one 'tag' strings ?? though OP didn't asked it. But the approach don't seem good to me. Edit: you have already mentioned I din't read. – Grijesh Chauhan Apr 15 '14 at 18:06