1

Scenario

We all know that trying to sort numbers alphabetically ends up with things like

123, 234, 5, 76, 9

But let's say you have a list of strings that look something like

123 Some title
234 Another title
5 More title
76 Titles abound
9 Last title

and you want it sorted by the size of the number in the first word of each title.

Expected result

5 More title
9 Last title
76 Titles abound
123 Some title
234 Another title

Question

Is there a nice way to sort this way, either by going via a different data structure, or otherwise?

Details

I entertained the thought of turning into some sort of dict or associated array such as

5: More title,
//...

but the numbers aren't necessarily unique for my use-case.

Alec
  • 1,986
  • 4
  • 23
  • 47
  • Why not store a list of words at each key of your dictionary? You can used an `OrderedDict` to keep the keys in ascending order. – Charles Dupont May 11 '21 at 20:30
  • @CharlesDupont - I'm having trouble visualizing what you mean. So a dict where the key is just the integers 1, 2, 3... and the value is a list of the words, and then I could use a custom sort to sort numberically by the first word? – Alec May 11 '21 at 20:31
  • Your idea to use a dictionary seems like a good one. Since you said the numbers aren't necessarily unique, your dictionary could be something like: `{5:[first title, another title], 9: [last title], ...}` So basically you can store a list of multiple titles that have the same number to get around the non-uniqueness of the numbers. And an `OrderedDict` is just a special case of a dictionary where you can keep all the keys in ascending order so that you can do an easy print-out or whatever when you are done parsing your input and building the dictionary. – Charles Dupont May 11 '21 at 20:33
  • The flagged duplicate link splits on `.`. The idea for your case would be similar. You use spaces. So you can split on the first space only and go from there. Example, if you have: `s = "123 bob is cool"`. Then doing this: `s.split(None, 1)` will give: `['123', 'bob is cool']`. Doing this can also compliment going down the path of using the dictionary solution discussed in the comments. – idjaw May 11 '21 at 20:36
  • @idjaw - That's fine. That thread answers my question quite nicely. I tried searching for it, but that one didn't show up. – Alec May 11 '21 at 21:39

2 Answers2

1

Use a lambda in your call to the sorted function. If these are your lines read in as a list of strings:

lines = ['123 Some title', '234 Another title', '5 More title', '76 Titles abound', '9 Last title']

# split the string into columns by whitespace, then cast the first
# column to an integer, and use that value to sort the strings.
sorted_lines = list(sorted(lines, key=lambda x: int(x.split()[0])))

You can use the fact that the strings are whitespace delimited, and you want to sort by the first column if cast as an integer. This yields the result you desired.

jrd1
  • 10,358
  • 4
  • 34
  • 51
0

You can use dictionary to store your titles and dict comprehension to sort them.

titles = {int(title.split()[0]):' '.join(title.split()[1:])for title in lst}
newTitles = {tup[0]:tup[1] for tup in sorted(titles.items())}
Buddy Bob
  • 5,829
  • 1
  • 13
  • 44
  • `title.split(' ')` should be: `title.split()` as `split` uses whitespace by default as a delimiter. – jrd1 May 11 '21 at 20:42