7

I have searched lot of time for this. I have got some idea about sorting using key parameter.

I have a list of tuple like this. It's got by OpenCV Hough Circle detection.

correctC = [(298, 172, 25), (210, 172, 25), (470, 172, 25), (386, 172, 22), (648, 172, 25), (384, 44, 22), (558, 110, 22), (562, 170, 25), (382, 108, 25), (734, 172, 25), (126, 172, 24), (646, 44, 22), (296, 110, 23), (126, 234, 26), (470, 236, 25), (296, 44, 25), (208, 108, 24), (38, 170, 25), (730, 110, 22), (730, 44, 25), (468, 110, 23), (468, 44, 25), (208, 44, 25), (124, 44, 22), (558, 44, 22), (36, 110, 24), (36, 44, 22), (298, 234, 26), (210, 236, 25), (648, 234, 25), (732, 234, 22), (562, 234, 26), (384, 236, 25), (38, 234, 26), (646, 110, 25), (124, 112, 27)]

It has 3 values. center coordinate(x,y) and radius.

I need to sort all tuples using it's x and y value.

I can do this sorting separately.

xS=sorted(correctC,key=lambda correctC: correctC[0])

This is sort according to x value only.

yS=sorted(correctC,key=lambda correctC: correctC[1])

This is sort according to y value only.

How can I do both(according to x value and y value) using one expression?

I'm using Python 2.7

4
  • 1
    What are the definitions of less than, equal to, and greater than for x and y? Specifically, which is less, (1, 2, 3) or (2, 1, 3), or are they considered equal for sorting? Or should you convert x and y to polar coordinates and use the length for sorting? Commented Apr 13, 2017 at 17:40
  • correctC is a bad name for the lambda argument, since you're reusing the same variable name for the list and its elements. Commented Apr 13, 2017 at 17:42
  • 1
    You should add the expected output to your question. Commented Apr 13, 2017 at 20:36
  • Does this answer your question? Sort a list by multiple attributes? Commented Aug 14, 2021 at 13:22

6 Answers 6

7

In this particular case, if you don't care about how the points with equal x, y value are arranged, just calling sort will do the job. Tuples are sorted in lexicographic order.

correctC.sort()

If you want to be more explicit, just do as the other answer tells:

correctC.sort(key=lambda t: (t[0], t[1]))
Sign up to request clarification or add additional context in comments.

Comments

4

From what I can see, this helps:

sorted(correctC, key=lambda correctC:[correctC[0],correctC[1]])

Sorted result:

[(36, 44, 22), (36, 110, 24), (38, 170, 25), (38, 234, 26), (124, 44, 22), (124, 112, 27), (126, 172, 24), (126, 234, 26), (208, 44, 25), (208, 108, 24), (210, 172, 25), (210, 236, 25), (296, 44, 25), (296, 110, 23), (298, 172, 25), (298, 234, 26), (382, 108, 25), (384, 44, 22), (384, 236, 25), (386, 172, 22), (468, 44, 25), (468, 110, 23), (470, 172, 25), (470, 236, 25), (558, 44, 22), (558, 110, 22), (562, 170, 25), (562, 234, 26), (646, 44, 22), (646, 110, 25), (648, 172, 25), (648, 234, 25), (730, 44, 25), (730, 110, 22), (732, 234, 22), (734, 172, 25)]

7 Comments

Cleaner way to write the lambda, since OP is using Python 2: key= lambda (x, y, z): (x, y). Or lambda tup: tup[:2] for Python 3.
@timgeb Isn't this the default sort order for tuples anyway? (Other than you are ignoring the third element.)
correctC is a bad name for the lambda argument, since you're reusing the same variable name for the list and its elements. (I see that that name choice came from the question itself, though.)
@trust512 Thanks for the answer.... But look, 18 and 19 / 34 and 35 elements...that elements are not sorted correctly. 18 = (384, 236, 25) 19 = (386, 172, 22) Above 2 tuples are not correctly sorted according to y value and 34 and 35 34 = (732, 234, 22) 35 = (734, 172, 25) I also can see it from my last result like this, drive.google.com/file/d/0B53F0wBGnYhddktMV1ZTQlhGZHc/…
@user119o: "Above 2 tuples are not correctly sorted according to y value" - yeah, because they're sorted by x value. The circles in your picture aren't arranged in perfect columns. If you want to detect the approximate grid structure and order the circles by that structure, you'll need something a lot more complex than a sort by two keys.
|
4

For anyone confused by the combination of

  • Unclear question
  • Accepted answer
  • OP user119o's comments

It looks like the OP wanted something like this:

sortedC = sorted(correctC)
for index in range(0, len(sortedC), 4):
    sortedC[index:index + 4] = sorted(sortedC[index:index + 4], key=lambda x: x[1])

The second column of tuples shows the expected output (which should have been included in the question):

 0  ( 36,  44,  22)  ( 36,  44,  22)  
 1  ( 36, 110,  24)  ( 36, 110,  24)  
 2  ( 38, 170,  25)  ( 38, 170,  25)  
 3  ( 38, 234,  26)  ( 38, 234,  26)  
 4  (124,  44,  22)  (124,  44,  22)  
 5  (124, 112,  27)  (124, 112,  27)  
 6  (126, 172,  24)  (126, 172,  24)  
 7  (126, 234,  26)  (126, 234,  26)  
 8  (208,  44,  25)  (208,  44,  25)  
 9  (208, 108,  24)  (208, 108,  24)  
10  (210, 172,  25)  (210, 172,  25)  
11  (210, 236,  25)  (210, 236,  25)  
12  (296,  44,  25)  (296,  44,  25)  
13  (296, 110,  23)  (296, 110,  23)  
14  (298, 172,  25)  (298, 172,  25)  
15  (298, 234,  26)  (298, 234,  26)  
16  (382, 108,  25)  (384,  44,  22)  True
17  (384,  44,  22)  (382, 108,  25)  True
18  (384, 236,  25)  (386, 172,  22)  True
19  (386, 172,  22)  (384, 236,  25)  True
20  (468,  44,  25)  (468,  44,  25)  
21  (468, 110,  23)  (468, 110,  23)  
22  (470, 172,  25)  (470, 172,  25)  
23  (470, 236,  25)  (470, 236,  25)  
24  (558,  44,  22)  (558,  44,  22)  
25  (558, 110,  22)  (558, 110,  22)  
26  (562, 170,  25)  (562, 170,  25)  
27  (562, 234,  26)  (562, 234,  26)  
28  (646,  44,  22)  (646,  44,  22)  
29  (646, 110,  25)  (646, 110,  25)  
30  (648, 172,  25)  (648, 172,  25)  
31  (648, 234,  25)  (648, 234,  25)  
32  (730,  44,  25)  (730,  44,  25)  
33  (730, 110,  22)  (730, 110,  22)  
34  (732, 234,  22)  (734, 172,  25)  True
35  (734, 172,  25)  (732, 234,  22)  True

Where there is a True in the fourth column, the expected output differs from sorted(correctC).

Comments

2

Why do you need to provide a key at all? Tuples are sorted lexicographically ("dictionary order")by default. The first elements will be compared. If they are the same, then the second elements of each tuple will be compared, and so on. meaning that the first element is compared and if they are the same, then go to the next element (basically "dictionary ordering"). If you rely on this, you will get exactly what you want, other than if two circles have the same center, then they will also be sorted by radius.

Comments

2

Assuming that you want to sort by distance from the origin, this is what you want:

import math

sortedC = sorted(correctC, 
                 cmp=lambda lhs, rhs: cmp(math.sqrt(lhs[0] ** 2 + lhs[1] ** 2),
                                          math.sqrt(rhs[0] ** 2 + rhs[1] ** 2)))

1 Comment

Thanks...I got lot of ideas from your answer. Actually I got the idea about what i want to do after your answer. Actually it's not about sort by distance... you can see what I wanted in this picture: drive.google.com/file/d/0B53F0wBGnYhdWkRiN1pNVXNXYlE/…
0

You can solve this problem writing a lambda function for you or using built-in itemgetter() offered by python

Solution - 01:

sorted_correctC = sorted(correctC, key = lambda x : x[0:2])
print(sorted_correctC)

Solution - 02

from operator import itemgetter

sorted_correctC2 = sorted(correctC, key = itemgetter(0,1))
print(sorted_correctC2)

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.