I would like to sort list A based on list B(descending order) such that if two list A,B are
A=["k","a","l","d"]
B=[4,3,7,22]
after sorting, ( sort A based on desc(B) )
A=["d","l","k","a"]
However if B=[0,0,0,0]
I would like A to remain A=["k","a","l","d"] after sorting too
so wherever values are equal, the original order must be retained.
if B=[0,22,5,0] and A=["k","a","l","d"]
then, after sorting, A=["a","l","k","d"]
I have tried using A= [x for _,x in sorted(zip(B,A),reverse=True)],
- with if
A=["k","a","l","d"]andB=[0,0,0,0], this givesA=["a","d","k","l"]but I want A to remainA=["k","a","l","d"] - with if
A=["k","a","l","d"]andB=[0,22,5,0], this givesA=["a","l","d","k"]but I want A to beA=["a","l","k","d"]
How do I achieve this?
CodePudding user response:
Use the key parameter of sorted
A = ["k", "a", "l", "d"]
Bs = [[4, 3, 7, 22], [0, 0, 0, 0], [0, 22, 5, 0]]
for B in Bs:
res = [a for _, a in sorted(enumerate(A), key=lambda x: B[x[0]], reverse=True)]
print(B, res)
Output
[4, 3, 7, 22] ['d', 'l', 'k', 'a']
[0, 0, 0, 0] ['k', 'a', 'l', 'd']
[0, 22, 5, 0] ['a', 'l', 'k', 'd']
As an alternative, you could use:
it_B = iter(B)
res = sorted(A, key=lambda _: next(it_B), reverse=True)
Both ideas work because Timsort (the underlying algorithm of sorted) is stable. Since you are using just one key, when the values are equal, they conserve the appearance order.
CodePudding user response:
You can create a dict that maps A to B, and use the mapping as a key function to sort A:
order = dict(zip(A, B))
output = sorted(A, key=order.get, reverse=True)
Demo: https://replit.com/@blhsing/FailingCloseTruespace#main.py
CodePudding user response:
Easiest method I've found is to use numpy's Argsort.
index = np.argsort(B)
a = a[index]
Order is kept if they are all the same (i.e. [0,0,0,0]).
