Учитывая два разных списка, которые имеют общие элементы и имеют разный размер, как изменить порядок второго списка на основе порядка элементов первого? Например:
Для:
a = ['a', 'b', 'e', 'z', 'f']
b = ['a', 'f', 'b', 'z', 'g', 'h']
Как переупорядочить список b в:
['a', 'b', 'z', 'f', 'g', 'h']
Для:
a = ['a', 'c', 'j', 'r' , 'p']
b = ['b', 'c', 'a']
Как переупорядочить список b в:
['a', 'c', 'b']
До сих пор я пытался:
[x for y, x in sorted(zip(a, b))]
Однако я не понимаю, как контролировать тот факт, что списки имеют разный размер. Как я могу изменить порядок второго списка на основе вышеуказанных ограничений?
Спасибо @trincot b
, как мне решить эту проблему?
Вам решать, как вы хотите, чтобы такие сценарии разыгрывались. Можете ли вы отредактировать свой вопрос, где b
и a
имеют разные частоты одного и того же символа, и предоставить ожидаемый результат для каждого примера, чтобы мы могли понять, в чем заключается логика?
Вы можете предоставить ключевую функцию для сортировки на основе индекса.
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)
А как насчет повторяющихся элементов, это тоже сработает? Спасибо за помощь!
@JDo Это должно работать; он по-прежнему будет сортироваться на основе индекса в файле a. Ты пробовал это?
вы можете сопоставить элементы списка a
с числовым порядком, а затем использовать функцию сортировки python для сортировки номера
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)
изменить: @jferard исправил критерии случая, где как упорядочить элемент, если элемент в списке b отсутствует в списке a.
Будет ли это работать в случае повторяющихся элементов в любом из списков?
да, но в этом случае вам нужно решить для повторяющегося элемента в списке a, отдаем ли мы предпочтение порядку первому вхождению элемента или последнему, по умолчанию он отдает его последнему
Хорошо, что это позволяет избежать повторных вызовов a.index()
(что равно O(N)).
Если я не ошибаюсь, следует order.get(x, len(a))
ставить пропущенные значения после всех известных значений a
. Если a
длиннее b
, некоторые значения будут смещены. Например. a = ['a', 'b', 'e', 'z', 'f', 'o', 'u', 'w']
и b = ['a', 'f', 'b', 'z', 'w', 'h']
-> ['a', 'b', 'z', 'f', 'h', 'w']
, но должно быть ['a', 'b', 'z', 'f', 'w', 'h']
.
@jferard да, вы правы, обновленное решение
Вы можете создать dict
базовый индекс a
. Это работает для повторяющихся элементов в b
, а для элементов, не существующих в a
, мы можем использовать 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}
Благодаря @Kelly Bundy, для более короткого подхода мы можем написать, как показано ниже:
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))
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)
Помните, что Stack Overflow предназначен не только для решения непосредственной проблемы, но и для того, чтобы помочь будущим читателям найти решения похожих проблем, что требует понимания базового кода. Это особенно важно для членов нашего сообщества, которые являются новичками и не знакомы с синтаксисом. Учитывая это, можете ли вы отредактировать свой ответ, включив в него объяснение того, что вы делаете, и почему вы считаете, что это лучший подход?
Могут ли
b
быть дубликаты? Что происходит тогда? Следует ли переместить дубликат в конец, если уa
нет дубликата для него?