How to reorder two lists of different size based on one list?

Question:

Given two different lists which share elements in common and have different size, how to reorder the second list based on the order of the elements of the first one? For example:

For:

a = ['a', 'b', 'e', 'z', 'f']
b = ['a', 'f', 'b', 'z', 'g', 'h']

How to reorder list b into:

['a', 'b', 'z', 'f', 'g', 'h']

For:

a = ['a', 'c', 'j', 'r' , 'p']
b = ['b', 'c', 'a']

How to reorder list b into:

['a', 'c', 'b']

So far I tried to:

[x for y, x in sorted(zip(a, b))]

However, I dont understand how to control the fact that the lists have different size. How could I reorder the second list based on the above restrictions?

Asked By: J Do

||

Answers:

You can provide a key function to sort based on the index.

a = ['a', 'b', 'e', 'z', 'f']
b = ['a', 'f', 'b', 'z', 'g', 'h']
from math import inf
res = sorted(b, key=lambda x: a.index(x) if x in a else inf)
print(res)
Answered By: Unmitigated

you can map the list a elements to numerical order and then use python sort functionality of sorting number

a = ['a', 'b', 'e', 'z', 'f']
b = ['a', 'f', 'b', 'z', 'g', 'h']

order = {value:index for index, value in enumerate(a)}

solution = sorted(b, key=lambda x: order.get(x, len(b)+len(a)))
print(solution)

edit: @jferard corrected the case critera where how to order element if element in list b not present in list a.

Answered By: sahasrara62

You can create dict base index of a. This works for repeated item in b and for items do not exist in a we can use itertools.count.

from itertools import count

a = ['a', 'b', 'e', 'z', 'f']
b = ['a', 'a', 'f', 'f', 'b', 'z', 'z', 'g', 'h', 'g', 'h', 'e']


dct_enum = {j:i for (i, j) in enumerate(a)}
idx_not_exist = count(len(a))


dct_index = {}
for i in b:
    if i not in dct_index:
        if i in dct_enum:
            dct_index[i] = dct_enum[i]
        else:
            dct_index[i] = next(idx_not_exist)


sorted(b, key=dct_index.get)
# ['a', 'a', 'b', 'e', 'z', 'z', 'f', 'f', 'g', 'g', 'h', 'h']


# sort 'b' base:
# {'a': 0, 'b': 1, 'e': 2, 'z': 3, 'f': 4, 'g':5, 'h':6}

By thanks @Kelly Bundy, For a shorter approach, we can write like the below:

a = ['a', 'b', 'e', 'z', 'f']
b = ['a', 'a', 'f', 'f', 'b', 'z', 'z', 'g', 'h', 'g', 'h', 'e']


# python >= 3.7 
dct_index = {j:i for (i, j) in enumerate(dict.fromkeys(a+b))}


# Older python version
dct_index = {j:i for (i, j) in enumerate(a)}
for i in b:
    if i not in dct_index:
        dct_index[i] = len(dct_index)

# dct_index : {'a': 0, 'b': 1, 'e': 2, 'z': 3, 'f': 4, 'g': 5, 'h': 6}

print(sorted(b, key=dct_index.get))
Answered By: I'mahdi
a = ['a', 'c', 'j', 'r' , 'p']
b = ['b', 'c', 'a']

c = []

for i in b:
    if i in a:
        c.insert(a.index(i), i)

for i in b:
    if i not in a:
        c.append(i)

print(c)
Answered By: Zahouani Mourad