Sorting list based on values from another list
Shortest Code
[x for _, x in sorted(zip(Y, X))]
Example:
X = ["a", "b", "c", "d", "e", "f", "g", "h", "i"]
Y = [ 0, 1, 1, 0, 1, 2, 2, 0, 1]
Z = [x for _,x in sorted(zip(Y,X))]
print(Z) # ["a", "d", "h", "b", "c", "e", "i", "f", "g"]
Generally Speaking
[x for _, x in sorted(zip(Y, X), key=lambda pair: pair[0])]
Explained:
zip
the twolist
s.- create a new, sorted
list
based on thezip
usingsorted()
. - using a list comprehension extract the first elements of each pair from the sorted, zipped
list
.
For more information on how to set\use the key
parameter as well as the sorted
function in general, take a look at this.
How to sort one list and re-sort another list keeping same relation python?
You could use this:
list1, list2 = zip(*sorted(zip(list1, list2)))
or this:
order = sorted(range(len(list1)), key=lambda i: list1[i])
list1 = [list1[i] for i in order]
list2 = [list2[i] for i in order]
The first one makes a new list that has matching pairs from list1
and list2
, then sorts the pairs, which will mainly focus on the values that came from list1
, and use the list2
value as a tiebreaker. Then zip(*new_list)
is a standard Python trick for splitting the pairs back into separate lists. It combines all the pairs together to make a new list with two long rows, one with the first item from each pair and one with the second item. Then assigning that list to two variables splits it into two lists.
The second one creates indexes for the items in both lists, then sorts the indexes using the corresponding item from list1
as a key. Then it retrieved the items from each list using the new ordering.
Or this hybrid may be more readable:
sorted_pairs = sorted(zip(list1, list2))
list1 = [v1 for v1, v2 in sorted_pairs]
list2 = [v2 for v1, v2 in sorted_pairs]
Python 3.x -- sort one list based on another list and then return both lists sorted
Is it possible to merge the last two lines into one line?
Yes it is. ordered_candidates
excludes the points from the result, since you only choose the candidates with [x for _, x in...]
. This basically only selects the second item from each tuple. Additionally, ordered_points
sorts only the points. They both also sort in reverse with reverse=True
.
Seems like you can just modify ordered_candidates
to include both items in the (point, candidate)
pairs.
>>> points = [4,7,3,2,7]
>>> candidates = ['a', 'b', 'c', 'd', 'e']
>>> sorted(zip(points, candidates), reverse=True)
[(7, 'e'), (7, 'b'), (4, 'a'), (3, 'c'), (2, 'd')]
How to sort two lists (which reference each other) in the exact same way
One classic approach to this problem is to use the "decorate, sort, undecorate" idiom, which is especially simple using python's built-in zip
function:
>>> list1 = [3,2,4,1, 1]
>>> list2 = ['three', 'two', 'four', 'one', 'one2']
>>> list1, list2 = zip(*sorted(zip(list1, list2)))
>>> list1
(1, 1, 2, 3, 4)
>>> list2
('one', 'one2', 'two', 'three', 'four')
These of course are no longer lists, but that's easily remedied, if it matters:
>>> list1, list2 = (list(t) for t in zip(*sorted(zip(list1, list2))))
>>> list1
[1, 1, 2, 3, 4]
>>> list2
['one', 'one2', 'two', 'three', 'four']
It's worth noting that the above may sacrifice speed for terseness; the in-place version, which takes up 3 lines, is a tad faster on my machine for small lists:
>>> %timeit zip(*sorted(zip(list1, list2)))
100000 loops, best of 3: 3.3 us per loop
>>> %timeit tups = zip(list1, list2); tups.sort(); zip(*tups)
100000 loops, best of 3: 2.84 us per loop
On the other hand, for larger lists, the one-line version could be faster:
>>> %timeit zip(*sorted(zip(list1, list2)))
100 loops, best of 3: 8.09 ms per loop
>>> %timeit tups = zip(list1, list2); tups.sort(); zip(*tups)
100 loops, best of 3: 8.51 ms per loop
As Quantum7 points out, JSF's suggestion is a bit faster still, but it will probably only ever be a little bit faster, because Python uses the very same DSU idiom internally for all key-based sorts. It's just happening a little closer to the bare metal. (This shows just how well optimized the zip
routines are!)
I think the zip
-based approach is more flexible and is a little more readable, so I prefer it.
Note that when elements of list1
are equal, this approach will end up comparing elements of list2
. If elements of list2
don't support comparison, or don't produce a boolean when compared (for example, if list2
is a list of NumPy arrays), this will fail, and if elements of list2
are very expensive to compare, it might be better to avoid comparison anyway.
In that case, you can sort indices as suggested in jfs's answer, or you can give the sort a key function that avoids comparing elements of list2
:
result1, result2 = zip(*sorted(zip(list1, list2), key=lambda x: x[0]))
Also, the use of zip(*...)
as a transpose fails when the input is empty. If your inputs might be empty, you will have to handle that case separately.
Sorting a list based on values from another list and excluding elements in list from the sort?
You can use np.argsort
on the portion you want:
order = np.r_[0,np.argsort(A[1:-1]) + 1, len(A)-1]
a_new = np.array(A)[order]
b_new = np.array(B)[order]
c_new = np.array(C)[order]
Output:
[50000 -4000 -3000 8000 51000]
['Start' 'Cost1' 'Cost2' 'Profit1' 'End']
['50K' '-4k' '-3k' '8k' '51k']
Kotlin: Sort list based on another list (different objects)
The easiest approach would be to first create a mapping of the list you want to sort by. It should associate the id to the actual object.
Then you iterate the list you want to sort by and map it's values to the object you retrieved from the mapping you just created.
Here a minimal example:
// both can have more properties of course
data class Foo(val id: Int)
data class Bar(val id: Int)
val fooList = listOf(Foo(4), Foo(2), Foo(1), Foo(3))
val barList = listOf(Bar(1), Bar(2), Bar(3), Bar(4))
val idValueMap = barList.associateBy { it.id }
val sortedByOtherList = fooList.map { idValueMap[it.id] }
println(sortedByOtherList)
Result:
[Bar(id=4), Bar(id=2), Bar(id=1), Bar(id=3)]
Python, sort a list by another list
You can try passing a lambda
function to the key
parameter of the sorted()
built-in function:
a = ['c', 'd', 'B', 'a', 'e']
b = ['a001', 'B002', 'c003', 'd004', 'e005']
c = sorted(b, key = lambda x: a.index(x[0])) # ['c003', 'd004', 'b002', 'a001', 'e005']
Sorting a list based off of values in another list
Try this way:
Step 1: create a dictionary be getting key from the pdf's file name
In this,step I extract the digits only on the last string joined with .pdf
d={}
for p in pdfs:
key = re.findall(r'\d+',p.split()[-1].rstrip('.pdf'))[0]
d[key] = p
Step 2: creat a new list to store the file name according to the your invoice_ordering_list
new_pdf=[]
for k in invoice_ordering_list:
new_pdf.append(d[k])
Python sort list based on values in another list with matching pattern
That should work for you
sorted_L1 = sorted(L1, key=lambda x: 12 * int(x[2:].split('_')[0]) + L2.index(x[:3]))
Related Topics
Uninstall Python Built from Source
Set Chrome Browser Binary Through Chromedriver in Python
Fail During Installation of Pillow (Python Module) in Linux
How to Iterate Over Rows in a Dataframe in Pandas
Pandas Conditional Creation of a Series/Dataframe Column
Does Python Have a Ternary Conditional Operator
Django Server Killed Frequently
How to Install Pyodbc on Linux
Simulating Key Press Event Using Python For Linux
How to Clone a List So That It Doesn't Change Unexpectedly After Assignment
How to Remove Items from a List While Iterating
How to Split a List into Equally-Sized Chunks
How to Do Sed Like Text Replace With Python
Trouble Installing Scipy in Virtualenv on a Amazon Ec2 Linux Micro Instance
What's the Easiest Way to Escape HTML in Python