Matthias Calis
Matthias Calis

Reputation: 143

Python sort list and associated list

I have a rather simple question and I have found several answers to this question but I simply can't get my head around it.

I have a list of x-values (for a plot) and a equally long list of y-values. I want to sort the list of y-values and update my x-list accordingly. Suppose I have these lists

xVars = [1,2,3,4,5]
yVars = [9,7,1,3,5] 

After sorting this is the result I want:

xVars = [3,4,5,2,1]
yVars = [1,3,5,7,9] #this is now sorted

My point in doing this is that I want to plot the max y-values with the associated x-values.

I have encountered the itemgetter() function and the sorted(key=) but I understand neither (that is, they don't work but thatś rather due to me not understanding them than it is because they wouldn't work).

Many Thanks in advance!

EDIT: Many Thanks to all of you, I wish I could chose all of you as the correct answer but unfortunately I can. Your explanations have been very helpful and I have learned quite a bit more about python now. Thanks! :)

Upvotes: 1

Views: 1851

Answers (5)

Gareth Latty
Gareth Latty

Reputation: 88997

Here you can use the zip() function to do this nicely. First we zip the values into pairs.

You can use sorted() to sort the values. Sorted will use the first value of the tuple to sort by, so we place the item we wish to sort by first.

Now we use zip with the splat operator to reverse the zipping procedure, resulting in this nice one-liner:

yVars, xVars = zip(*sorted(zip(yVars, xVars)))

Which produces the wanted output:

>>> xVars = [1,2,3,4,5]
>>> yVars = [9,7,1,3,5] 
>>> yVars, xVars = zip(*sorted(zip(yVars, xVars)))
>>> xVars
(3, 4, 5, 2, 1)
>>> yVars
(1, 3, 5, 7, 9)

Note that these are tuples, so if you need lists again, just do a simple yVars, xVars = list(yVars), list(xVars) afterwards.

If you wish to expand this to more than two lists, just add more arguments to zip, and it will return more.

Note that this will sort by the first value, and then the second value on collisions. This means if you have repeated values, the order could be different to what you were expecting. In that case, you can specify your key absolutely:

yVars, xVars = zip(*sorted(zip(yVars, xVars), key=lambda item: item[0]))

Upvotes: 1

Duncan
Duncan

Reputation: 95652

You don't actually need to use zip for this. Just sort xVars using yVars as the sort key, then you can use the new xVars to rebuild yVars in the correct order:

>>> xVars = [1,2,3,4,5]
>>> yVars = [9,7,1,3,5]
>>> xVars = sorted(xVars, key=lambda i: yVars[i-1])
>>> yVars = [ yVars[i-1] for i in xVars ]
>>> xVars
[3, 4, 5, 2, 1]
>>> yVars
[1, 3, 5, 7, 9]

Also, if as you say you just want to get the largest y values with their associated x values then you can use heapq.nlargest instead of sorting the whole list. If you have long lists and only want a few large values this may be more efficient:

>>> xVars = [1,2,3,4,5]
>>> yVars = [9,7,1,3,5]
>>> from heapq import nlargest
>>> x_largest = nlargest(3, xVars, key=lambda i: yVars[i-1])
>>> y_largest = [ yVars[i-1] for i in x_largest ]
>>> x_largest, y_largest
([1, 2, 5], [9, 7, 5])

Upvotes: 0

tom stratton
tom stratton

Reputation: 678

Check out the zip and sorted functions...

zip(y,x) will return a LIST of tuples [(y1,x1) , (y2,x2), ... ]

sorted(zip(y,x)) will sort this list - by default on the first value in the tuples (the y's)

you can then turn this back into separate lists by using list comprehensions..

>>> xVars = [1,2,3,4,5]
>>> yVars = [9,7,1,3,5] 
>>> sorted_list= sorted(zip(yVars,xVars))
>>> sorted_x = [ b for a,b in sorted_list ]
>>> sorted_y = [ a for a,b in sorted_list ]
>>> print(sorted_x)
[3, 4, 5, 2, 1]
>>> print(sorted_y)
[1, 3, 5, 7, 9]

There are a couple of points here - in order to make the sort() easier I have changed the order of x and y so that it automatically sorts on the y values.

If you are not yet familiar with list comprehensions here is the equivalent syntax...

squares = [x**2 for x in range(10)]

is the same as...

>>> squares = []
>>> for x in range(10):
...     squares.append(x**2)
...
>>> squares
[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]

Good luck!

Upvotes: 0

MDT
MDT

Reputation: 471

The sorted(key=) function works as follows

xVars = [1,2,3,4,5]
yVars = [9,7,1,3,5]


xyZipped = zip(xVars, yVars)
sorted(xyZipped, key=lambda xyZipped: xyZipped[1])
print(xyZipped)

The key is a function (in this case a lambda function) that returns a single argument for the sorting to act on. The lambda function is returning the second item in the tuple, which is the yVar that has been zipped up with its corresponding xVar

Upvotes: 0

Wooble
Wooble

Reputation: 89897

>>> tmp = sorted(zip(xVars, yVars),key=lambda x: x[1])
>>> xVars = [x[0] for x in tmp]
>>> yVars = [x[1] for x in tmp]
>>> xVars
[3, 4, 5, 2, 1]
>>> yVars
[1, 3, 5, 7, 9]

Upvotes: 4

Related Questions