My question is very similar to these two links 1 and 2:
I have three different lists. I want to sort List1 based on List2 (in ascending order). However, I have repeats in List2. I then want to sort these repeats by List3 (in descending order). Confusing enough?
What I have:
List1 = ['a', 'b', 'c', 'd', 'e']
List2 = [4, 2, 3, 2, 4]
List3 = [0.1, 0.8, 0.3, 0.6, 0.4]
What I want:
new_List1 = ['b', 'd', 'c', 'e', 'a']
'b' comes before 'd' since 0.8 > 0.6. 'e' comes before 'a' since 0.4 > 0.1.
Approach : Zip the two lists. Create a new, sorted list based on the zip using sorted(). Using a list comprehension extract the first elements of each pair from the sorted, zipped list.
Use the zip() and sorted() Functions to Sort the List Based on Another List in Python. In this method, we will use the zip() function to create a third object by combining the two given lists, the first which has to be sorted and the second on which the sorting depends.
I think you should be able to do this by:
paired_sorted = sorted(zip(List2,List3,List1),key = lambda x: (x[0],-x[1]))
l2,l3,l1 = zip(*paired_sorted)
In action:
>>> List1 = ['a', 'b', 'c', 'd', 'e']
>>> List2 = [4, 2, 3, 2, 4]
>>> List3 = [0.1, 0.8, 0.3, 0.6, 0.4]
>>> paired_sorted = sorted(zip(List2,List3,List1),key = lambda x: (x[0],-x[1]))
>>> l2,l3,l1 = zip(*paired_sorted)
>>> print l1
('b', 'd', 'c', 'e', 'a')
Here's how it works. First we match corresponding elements from your lists using zip
. We then sort those elements based on the items from List2 first and (negated) List3 second. Then we just need to pull off the List1 elements again using zip
and argument unpacking -- Although you could do it easily with a list-comprehension if you wanted to make sure you had a list at the end of the day instead of a tuple.
This gets a little tougher if you can't easily negate the values in List3 -- e.g. if they're strings. You need to do the sorting in 2 passes:
paired = zip(List2,List3,List1)
rev_sorted = sorted(paired,reverse=True,key=lambda x: x[1]) #"minor" sort first
paired_sorted = sorted(rev_sorted,key=lambda x:x[0]) #"major" sort last
l2,l3,l1 = zip(*paired_sorted)
(you could use operator.itemgetter(1)
in place of lambda x:x[1]
in the above if you prefer). This works because python sorting is "stable". It doesn't re-order "equal" elements.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With