0

I have an array with these datas:

[['1', '7', '14'], ['1', '1', '3'], ['1', '12', '3'], ['2', '3', '1'], ['1', '4', '9']]

I like to sort it (multiple):

>>> sorted(datas,key=lambda x:(x[0], x[1]))
[['1', '1', '3'], ['1', '12', '3'], ['1', '4', '9'], ['1', '7', '14'], ['2', '3', '1']]    

but after sorted as it seems the 12 < 4. It should be:

[['1', '1', '3'], ['1', '4', '9'], ['1', '7', '14'], ['1', '12', '3'], ['2', '3', '1']]

Any idea? I need not natural sorting.

4
  • 1
    possible duplicate of Does Python have a built in function for string natural sort? Commented Mar 27, 2015 at 17:02
  • 1
    The issue is nothing to do with the fact you are sorting by multiple keys, it is simply that the string '12' is less than '4'. You want to use a natural sort, or alternatively you can cast the strings to int Commented Mar 27, 2015 at 17:03
  • vaultah wrote the good solution yet, but deleted it. Commented Mar 27, 2015 at 17:07
  • Thanks MJeffryes the cast the string to int is a right solution. Commented Mar 27, 2015 at 17:10

4 Answers 4

2

There is not wrong with sorted behaviour. Your data are lists of string, so it's doable.

>>> data = ['1', '12', '3', '2']
>>> sorted(data)
['1', '12', '2', '3']

If you want to sort as integer, it must be converted.

>>> sorted(data)
['1', '12', '2', '3']
>>> data = [['1', '7', '14'], ['1', '1', '3'], ['1', '12', '3'], ['2', '3', '1'], ['1', '4', '9']]
>>> sorted(data, key=lambda x: map(int, x))
[['1', '1', '3'], ['1', '4', '9'], ['1', '7', '14'], ['1', '12', '3'], ['2', '3', '1']]
Sign up to request clarification or add additional context in comments.

2 Comments

It's sorted with respect to all elements in list of list. But if you want to sorted by specific index in a list, it's not work
You asked about why the sorted's behaviour was that! That's the explanation.
1

Convert x[1] to int(x[1]):

sorted(d,key=lambda x:(int(x[0]), int(x[1])))

Output:

[['1', '1', '3'], ['1', '4', '9'], ['1', '7', '14'], ['1', '12', '3'], ['2', '3', '1']]

Comments

1

You are comparing strings, not ints. Therefor the order you get is the lexicographical order. If you convert to int first

sorted(data, key=lambda x:(int(x[0]), int(x[1])))

you will get the desired result

[['1', '1', '3'], ['1', '4', '9'], ['1', '7', '14'], ['1', '12', '3'], ['2', '3', '1']]

5 Comments

It's answer looks like my answer. but I answer this first, may be 3 mins before @Sotech & chokola
@SakibAhammed Sometimes when an answer is simple enough, multiple people do legitimately post nearly the same answer within the first few minutes.
@cpburnz...Hmm i know that. but he was posted after 3 mins from me, this is a so much time for that answer
@SakibAhammed It's not really that long. If someone came to this page before anyone answered, and then went to write an answer, they would not know an answer was posted a couple minutes earlier until they post it and reload the page. The new answer notifications are not perfect or instant (and can be missed).
You're right Sakib. Sorry I didn't look through the answers thoroughly. The points are yours.
0

Currently your sort is working on tuples string values. String values are determined similarly to any other iterable. When it compares two strings, it goes character by character from left-to-right or index 0 to index n-1 where n is the length of the iterable, until it finds one character that is larger than another. so when comparing '12' and '4', it notices that '4' is greater than '1' so it finishes right there. This system of ordering is known as lexicographical order.

To see the "value" of a character (In Python, a character is just a string of length 1), just use the ord function:

>>> ord('1')
49
>>> ord('4')
52

And to validate that the string '12' is indeed less than '4' because ord('1') < ord('4'):

>>> '12' < '4'
True

If you want to sort by the integer values of the strings, you have to convert the strings to ints by using the built-in int constructor.

sorted(datas,key=lambda x: (int(x[0]), int(x[1]))

Or if you want to cleanly handle iterables of all sizes, simply use a tuple-generator for the key:

sorted(datas,key=lambda x: tuple(int(e) for e in x))

Comments

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.