nad
nad

Reputation: 2860

indirect sorting a list in python

I have a list that I need to sort

list_of_sent = ['a5 abc xyz','w1 3 45 7','a6 abc deg','r4 2 7 9']

The rules are as follows.

In the above example, the expected output is

['a5 abc deg','a6 abc xyz','r4 2 7 9','w1 3 45 7']

I understand this is some form of indirect sorting but not sure how to approach that. So far, I have separated the list in terms of whether the 2nd and onward items have numbers or not. But not sure how to proceede after that.

def reorderLines(logLines):
    numList = []
    letterList = []
    hashMap = {}

    for item in logLines:
        words = item.split()
        key= words[0]
        hashMap[key] = item
        if words[1].isdigit():
            numList.append(item)
        else:
            letterList.append(item)

    #sort each list individually
    print(numList)
    print(letterList)

EDIT:

This will output

['a5 abc xyz','a6 abc deg']
['w1 3 45 7','r4 2 7 9']

How do I proceed afterwards to reach to the output of

['a5 abc deg','a6 abc xyz','r4 2 7 9','w1 3 45 7']

Upvotes: 0

Views: 594

Answers (3)

Azat Ibrakov
Azat Ibrakov

Reputation: 10989

We can write sorting key as follows:

def sorting_key(element):
    second_substring = element.split()[1]
    return second_substring.isdecimal(), element

then use it in sorted builtin like

>>> list_of_sent = ['a5 abc xyz', 'w1 3 45 7', 'a6 abc deg', 'r4 2 7 9']
>>> sorted(list_of_sent, key=sorting_key)
['a5 abc xyz', 'a6 abc deg', 'r4 2 7 9', 'w1 3 45 7']

or if we don't need old order we can sort list_of_sent in place (may be more efficient, at least will not occupy additional memory for a new list):

>>> list_of_sent = ['a5 abc xyz', 'w1 3 45 7', 'a6 abc deg', 'r4 2 7 9']
>>> list_of_sent.sort(key=sorting_key)
>>> list_of_sent
['a5 abc xyz', 'a6 abc deg', 'r4 2 7 9', 'w1 3 45 7']

More info about differences between sorted & list.sort could be found in this thread.

Upvotes: 2

kkblue
kkblue

Reputation: 183

After the comment do these:

newlist = []
numList.sort()
letterList.sort()
newlist = letterList + numList
print(numList)
print (letterList)
print (newlist)

Upvotes: 0

abarnert
abarnert

Reputation: 365925

The answer to your direct question is simple.

You've already worked out how to split the list into these two lists:

['a5 abc xyz','a6 abc deg']
['w1 3 45 7','r4 2 7 9']

Now, you just need to sort each one, and add them together.


But this really isn't the right approach in the first place. When looking at how to do a custom sort, the first thing you should do is ask yourself whether some other list, which you could easily transform this one into, would be trivial to sort.

For example, imagine you had this:

list_of_sent = [
    (False, 'a5 abc xyz'), 
    (True, 'w1 3 45 7'),
    (False, 'a6 abc deg'),
    (True, 'r4 2 7 9')]

… where that first value in each tuple is True iff the second word in the string is a number.

If that were your list, you could just call sort or sorted on it, and you'd be done.

So, can you transform each of your strings into a tuple like that? Sure you can:

def flagnumbers(words):
    isnumber = words.split()[1].isdigit()
    return isnumber, words

And how, you can just pass that as the key function to sort your list:

list_of_sent = ['a5 abc xyz','w1 3 45 7','a6 abc deg','r4 2 7 9']
print(sorted(list_of_sent, key=flagnumbers))

That's it.

The Sorting HOWTO in the docs covers key functions in more detail, with some nice examples.

Upvotes: 3

Related Questions