44

I have a list

mylist = [['123', 'BOOL', '234'], ['345', 'INT', '456'], ['567', 'DINT', '678']]

I want to sort it with the order of 1. DINT 2. INT 3. BOOL

Result:

[['567', 'DINT', '678'], ['345', 'INT', '456'], ['123', 'BOOL', '234']]

I've seen other similar questions in stackoverflow but nothing similar or easily applicable to me.

3
  • you have a syntax error: '345 is not closed. Commented Jan 8, 2013 at 4:36
  • "I want to sort it with the order of 1. DINT 2. INT 3. BOOL". What order is that? If I add another item ['317.3', 'FLOAT', '268.0'], how do I know where it goes in the sorted output? Commented Jan 8, 2013 at 4:55
  • @KarlKnechtel Well, the complete application of this is to sort REAL (float), DINT, INT, SINT, BOOL. This is the order I want (big to small). This question here is just for illustrative purpose. '123', '234', '345'... all has no real meaning. Commented Jan 8, 2013 at 6:31

5 Answers 5

88
SORT_ORDER = {"DINT": 0, "INT": 1, "BOOL": 2}

mylist.sort(key=lambda val: SORT_ORDER[val[1]])

All we are doing here is providing a new element to sort on by returning an integer for each element in the list rather than the whole list. We could use inline ternary expressions, but that would get a bit unwieldy.

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

3 Comments

@SeanVieira, how would you extend this when you have a sort order, but sometimes not all keys are in the list we want to sort?
Python has a .get method for dictionaries that can be used, so you could do lambda val: SORT_ORDER.get(val[1], "MY DEFAULT SORT ORDER VALUE") @joddm
Nice, but taking this as inspiration, I prefer SORT_ORDER = ["DINT", "INT", "BOOL"] mylist.sort(key=lambda val: SORT_ORDER.index(val)). I suppose maybe that's not as fast as using indexing? but it seems easier to interpret.
3

Another way could be; set your order in a list:

indx = [2,1,0]

and create a new list with your order wished:

mylist = [mylist[_ind] for _ind in indx]

Out[2]: [['567', 'DINT', '678'], ['345', 'INT', '456'], ['123', 'BOOL', '234']]

Comments

1

You can define an explicit order by a list:

def explicit_order(xs):
    """Return a key function that, when passed to sort or sorted, will sort
    the elements in the order they appear in this list.
    """
    keys = {x: i for i, x in enumerate(xs)}
    def key_function(x):
        return keys[x]
    return key_function

order = explicit_order(['DINT', 'INT', 'BOOL'])
sorted(['BOOL', 'INT'], key=order) # = ['INT', 'BOOL']

Since in your example you also have to extract the string from your tuples, you'll have a slightly more complex key-function:

sorted(mylist, key=lambda x: order(x[1]))

1 Comment

Note that, as written, this throws if any items in the list to be sorted don't appear in the original list passed to explicit_order.
0

Since that is not in aphabetical order I don't think there is one single function that can sort it but what you could do is create a new list and then append. This is kind of a cheap method of doing it; but it gets the job done.

newlist=[];
for sub_list in mylist:
     if(sub_list[1] == 'DINT']):
          newlist.append(sub_list);

for sub_list in mylist:
     if(sub_list[1] == 'INT']):
         newlist.append(sub_list);

for sub_list in mylist:
     if(sub_list[1] == 'BOOL']):
            newlist.append(sub_list);

7 Comments

Braces? from __future__ import braces ;-) Also, see my answer - you only need to traverse the list once :-)
Yeah I prefer the other answer. Two-liner solution.
Even if this approach made sense, for the love of all that is holy, use list comprehensions, or filter, or something.
@KarlKnechtel: I don't know how you can say even if this approach made sense... I tested it and it works. But there is a thing called constructive criticism; no need to be rude to strangers.
One thing I always do when setting up loop(s) is try to think how I can reduce the number of passes through the data. In this case, you are looping through three times to find three different variables, so the challenge is finding a way where you can get all of your information in a single pass (since you will encounter all of the variables in a single pass). Sean's solution uses a dictionary to accomplish this, so each time you encounter an item you know exactly where it goes. Also, you should definitely take a look at list comprehensions - you'll quickly learn to love them :)
|
-1

python 3.2

  1. sorted(mylist,key=lambda x:x[1][1])

  2. sorted(mylist,reverse=True)

1 Comment

The first option works but assumes that the tag names won't change. The second option is not what the OP wants.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.