Related problem : in the final part I'm looking for a quicker method than a nested for loop.
Say we have a list a = [a_0, a_1, ..., a_n]
. We create a deep copy of a
called b = [b_0, b_1, ..., b_n]
, in which b_i
and a_i
are identical objects but stored separately. Now we perform a certain sorting algorithm some_sort
on b
to get an ordering order_b = [b'_0, b'_1, ..., b'_n]
in which those b'_i
are the
same objects
objects in b
permuted (since the some_sort
algorithm is destructive, elements in order_b
are no longer identical to those in b
, but the references are maintained). Now, I want a
to be sorted according to the same ordering in order_b
, ie, get an ordering order_a = [a'_0, a'_1, ..., a'_n]
which is a permutation from a
in the same way as order_b
is permuted from b
, but I can't perform the sorting algorithm some_sort
on a
because that algorithm is destructive. Is there any quick way to do this?
Example: a = [a_0, a_1, a_2, a_3]
, deep copy of a
is b = [b_0, b_1, b_2, b_3]
. The resulting ordering on b
is order_b = [b_3, b_2, b_0, b_1]
, then what I want is to obtain order_a = [a_3, a_2, a_0, a_1]
according to order_b
.
import copy
a = [2,4,3,1]
Out[94]: [2, 4, 3, 1]
#create a deep copy of a
b = copy.deepcopy(a)
Out[96]: [2, 4, 3, 1]
#add index of b and its value to a tuple
b1 = [(v,k) for k, v in enumerate(b)]
Out[98]: [(2, 0), (4, 1), (3, 2), (1, 3)]
#sort b1 (can using whatever criteria for sorting)
b1 = sorted(b1)
Out[100]: [(1, 3), (2, 0), (3, 2), (4, 1)]
#extract elements from a using the order of b1.
[a[e] for e in [e[-1] for e in b1]]
Out[101]: [1, 2, 3, 4]
You mentioned you keep the original b_i
reference in b'_i
, so you can create a reverse lookup of {b_i: idx}
, eg (pseudo):
mapping = {b'_i->b_i: idx for idx, b'_i in enumerate(order_b)}
[m for m, n in sorted(zip(a,b), key=lambda x: mapping[x[1]])]
Demo, take a list of numbers and letters, randomize the letters and return the numbers in the same order as the randomize letters:
In [1]:
import random
a = list(range(10))
b = list('abcdefghij')
b_ = random.sample(b, k=len(b))
''.join(b_)
Out[1]:
'idfehbgacj'
In [2]:
mapping = {k: idx for idx, k in enumerate(b_)}
[m for m, n in sorted(zip(a,b), key=lambda x: mapping[x[1]])]
Out[2]:
[8, 3, 5, 4, 7, 1, 6, 0, 2, 9]
i have simple solution for this:
a_ = [ a[i] for i in (b.index(j) for j in b_) ]
_or_
b_perm = [ b.index(j) for j in b_ ]
a_ = [ a[i] for i in b_perm ]
import random
a = list(range(10))
b = list('abcdefghij')
b_ = random.sample(b, k=len(b))
b_ = ['c', 'b', 'f', 'i', 'e', 'a', 'h', 'g', 'j', 'd']
a_ = [a[i] for i in (b.index(j) for j in b_)]
a_ = [2, 1, 5, 8, 4, 0, 7, 6, 9, 3]
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.