0

I have a list of strings that I have to sort and return in descending order but my code is not working. Could you please help?

lst1 = 'Tadashi Takahiro Takao Takashi Takayuki Takehiko Takeo Takeshi Takeshi'

def lineup_students(string):
    lst = string.split(' ')
    return sorted(lst, key = len, reverse = True)

print lineup_students(lst1)

My output:

['Takahiro', 'Takayuki', 'Takehiko', 'Tadashi', 'Takashi', 'Takeshi', 'Takeshi', 'Takao', 'Takeo']

Expected output:

['Takehiko','Takayuki','Takahiro','Takeshi', 'Takeshi', 'Takashi','Tadashi','Takeo','Takao']

This question is not a duplicate of how to sort by length of string followed by alphabetical order? or Python Sort List : sadly, neither the first nor the second have helped me to solve my problem (but if I missed something please let me know)

@Edit1: Thanks to Mike and tobspr that gave me part of the solution:

def lineup_students(string):
    lst = string.split(' ')
    return sorted(lst, key=lambda x: (len(x), x), reverse=True)

def lineup_students(string):
    lst = string.split(' ')
    lst.sort(reverse=True)
    lst.sort(key=len, reverse=True)
    return lst

The point is that the code seems not to work with this list of names:

['Shigekazu', 'Takeshi', 'Senichi', 'Ryuichi', 'Yoshio', 'Toshio', 'Noboru',
 'Mitsuo', 'Rafu', ''] 

should equal

['Shigekazu', 'Takeshi', 'Senichi', 'Ryuichi', 'Yoshio', 'Toshio', 'Noboru',
 'Mitsuo', 'Rafu']

@edit2: This answer seems to work:

def lineup_students(s):
    return sorted(s.split(), key=lambda i:(len(i),i), reverse=True)
Community
  • 1
  • 1

2 Answers2

1

Your expected output seems to expect them in reverse sorted order, that is, first sorted alphabetically descending, then by length descending:

>>> names = 'Tadashi Takahiro Takao Takashi Takayuki Takehiko Takeo Takeshi Takeshi'.split()
>>> names.sort(reverse=True)
>>> names.sort(key=len, reverse=True)
>>> names
['Takehiko', 'Takayuki', 'Takahiro', 'Takeshi', 'Takeshi', 'Takashi', 'Tadashi', 'Takeo', 'Takao']

Which gives me your expected result.

Your function would look like:

def lineup_students(string):
    lst = string.split(' ')
    lst.sort(reverse=True)
    return sorted(lst, key=len, reverse=True)
tobspr
  • 8,200
  • 5
  • 33
  • 46
  • Ok, it works..thank you! I made a mountain out of a molehill. But what if I change the imput with a random one? – Marco Giuseppe de Pinto Apr 23 '16 at 18:18
  • @MarcoGiuseppedePinto you would take the names as a second argument to your function. Just make sure you make a copy before calling sort, or use the method proposed by Mike to make sure you don't modify your input. – tobspr Apr 23 '16 at 18:20
  • Many thanks: if I understood, my function should be def lineup_students(string, names) right? Because I tried Mike code but I am getting stuck on some random testcases – Marco Giuseppe de Pinto Apr 23 '16 at 18:26
  • You should remove the string parameter then of course, so you take the list of names instaead of a string. Sorry If I explained it wrong. – tobspr Apr 23 '16 at 18:29
  • Do not be sorry, I am a rookie so my fault! – Marco Giuseppe de Pinto Apr 23 '16 at 18:30
1

Original Version

You can sort by length and value:

lst1 = 'Tadashi Takahiro Takao Takashi Takayuki Takehiko Takeo Takeshi Takeshi'

def lineup_students(string):
    lst = string.split(' ')
    return sorted(lst, key=lambda x: (len(x), x), reverse=True)

>>> lineup_students(lst1)
['Takehiko',
 'Takayuki',
 'Takahiro',
 'Takeshi',
 'Takeshi',
 'Takashi',
 'Tadashi',
 'Takeo',
 'Takao']

The key function sorts by length first. If two words have the same length, it uses the word itself as criterion, i.e. goes by the alphabetical order of the two words with same length.

Version after Edit

data = ['Shigekazu', 'Takeshi', 'Senichi', 'Ryuichi', 'Yoshio', 'Toshio', 'Noboru', 
        'Mitsuo', 'Rafu', '']

res = ['Shigekazu', 'Takeshi', 'Senichi', 'Ryuichi', 'Yoshio', 'Toshio', 'Noboru',
       'Mitsuo', 'Rafu']

def lineup_students(lst):
    lst = [x for x in lst if x]
    return sorted(lst, key=lambda x: (len(x), x), reverse=True)

Try it:

>>> lineup_students(data) == res
True
Mike Müller
  • 82,630
  • 20
  • 166
  • 161