2014-01-10 2 views
3

У меня есть два списка list1 и list2. Я нашел в stackoverflow очень простой метод для получения общих элементов в этих двух списках следующим образом: result = list(set(list1) & set(list2)). К сожалению, при этом порядок элементов в результирующем списке не сохраняется.Общие элементы между двумя списками и сохранение порядка элементов в двух списках

Например:

list1 = ['a', 'e', 't', 'b', 'c'] 
list2 = ['e', 'b', 'a', 'c', 'n', 's'] 

Я хочу, чтобы результат (общие элементы), чтобы быть в таком порядке ['e', 'a', 'b', 'c']. Поскольку, например, «e» находится в списке1 и в списке2 и находится в позиции 2 в списке1 и в позиции 1 в списке2, тогда как «a» находится в списке1 и в списке2 и находится в позиции 1 в списке1 и в позиции 3 в списке2, поэтому 'e' находится перед 'a', поскольку 2 + 1 < 1 + 3.

Итак, есть ли простой способ иметь общие элементы между двумя списками и сохранять порядок элементов?

+0

какой заказ вы хотели бы предположить, что «e» и «t» были заменены в списке1? – wim

+0

Каков ожидаемый результат для 'list1 = ['a', 'b']; песни2 = [ 'B', 'а'] '? Идя по вашему алгоритму, оба «a» и «b» имеют одинаковое позиционное значение «3», так что это на первом месте? – Kevin

+0

@ Kevin. В этом случае это не имеет значения, если результат [a, b] или [b, a] – shn

ответ

4
list1 = ['a', 'e', 't', 'b', 'c'] 
list2 = ['e', 'b', 'a', 'c', 'n', 's'] 

weights = defaultdict(int) 

for i, e in enumerate(list1): 
    weights[e] += i 

for i, e in enumerate(list2): 
    weights[e] += i 

>>> result = sorted(set(list1) & set(list2), key=lambda i: weights[i]) 
>>> result 
['e', 'a', 'b', 'c'] 
2

Вы можете использовать список понимание для фильтрации всех элементов из list1, которые также не принадлежат list2:

list1 = ['a', 'e', 't', 'b', 'c'] 
list2 = ['e', 'b', 'a', 'c', 'n', 's'] 

result = [item for item in list1 if item in list2] 
print result 

Результат:

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

Хотя это не соответствует желаемому результату в вашем главном сообщении, из вашего последующего комментария кажется, что это приемлемый результат.


Вы также можете продолжать использовать множественный подход, а затем отсортировать результаты постфактум с помощью алгоритма позиционирования вы описали:

list1 = ['a', 'e', 't', 'b', 'c'] 
list2 = ['e', 'b', 'a', 'c', 'n', 's'] 

items = set(list1) & set(list2) 
result = sorted(items, key=lambda element: list1.index(element) + list2.index(element)) 

print result 

Результат:

['e', 'a', 'b', 'c'] 
1

Вы можете сохранить порядок одного такого списка, сделав только один из них:

list1 = ['a', 'e', 't', 'b', 'c'] 
list2 = ['e', 'b', 'a', 'c', 'n', 's'] 

slist1 = set(list1) 
slist2 = set(list2) 

# list1 determines the ordering 
olist1 = [x for x in list1 if x in slist2] 

# list2 determines the ordering 
olist2 = [x for x in list2 if x in slist1] 

В принципе, вы перебираете один список и проверяете каждый элемент, чтобы узнать, находится ли он в другом. Это гарантирует, что ваш окончательный список находится в том же порядке, что и оригинал, но также и содержит только записи в обоих списках.

Использование наборов значительно ускоряет проверку включения.

Если вы хотите сделать что-либо более сложное, чем это (сделайте окончательный заказ в зависимости от индексов в обоих списках, например), то вам нужно будет более конкретно об этих деталях.

Редактировать: OK, вы отправили более подробную информацию о том, что вы хотите сделать. Не знаю, если это быстрый, но вы можете сделать что-то подобное, чтобы получить индексы:

list1_offsets = dict(x[::-1] for x in enumerate(list1)) 
list2_offsets = dict(x[::-1] for x in enumerate(list2)) 

total_list = slist1 & slist2 

total_offset = [(x, list1_offsets[x] + list2_offsets[x]) for x in total_list] 

final_list = [x[0] for x in sorted(total_offset, key=itemgetter(1))] 

В этом случае выход был ожидаемый ['e', 'a', 'b', 'c'].

+0

Это удаляет синглтоны, но также удаляет информацию, в которой дубликаты были ... –

+0

изменен ... но другой ответ - одно и то же, но теперь есть еще один ответ, который короче. может удалить это в ближайшее время. –

0

Ваша функция заказа кажется довольно странной, но нормально.Вам нужно найти пересечение и отсортировать его по вашей функции заказа в основном.

order_function = lambda val: list1.index(val) + list2.index(val) 
common = set(list1) & set(list2) 
indexed = [(order_function(v), v) for v in common] 
return [x[1] for x in sorted(indexed)] 
Смежные вопросы