2013-08-12 3 views
5

Я пытаюсь удалить дубликаты из 2 списков. поэтому я написал эту функцию:python удалить дубликаты из 2 списков

a = ["abc", "def", "ijk", "lmn", "opq", "rst", "xyz"] 

b = ["ijk", "lmn", "opq", "rst", "123", "456", ] 

for i in b: 
    if i in a: 
     print "found " + i 
     b.remove(i) 

print b 

Но я обнаружил, что соответствующие элементы, следующие за согласованным элементом, не удаляются.

Я получаю результат:

found ijk 
found opq 
['lmn', 'rst', '123', '456'] 

, но я ожидаю результат:

[ '123', '456']

Как я могу исправить свою функцию, чтобы делать то, что Я хочу?

спасибо.

+0

I дал вам решение, в котором хранятся как ваши списки, в том же порядке и удаляет дубликаты в каждом из них. Я думаю, это то, что вы искали. –

ответ

9

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

for i in b[:]: 
    if i in a: 
     b.remove(i) 


>>> b 
['123', '456'] 

Но, как насчет использования списка?

>>> a = ["abc", "def", "ijk", "lmn", "opq", "rst", "xyz"] 
>>> b = ["ijk", "lmn", "opq", "rst", "123", "456", ] 
>>> [elem for elem in b if elem not in a ] 
['123', '456'] 
+0

Если список 'a' растет дольше, может оказаться, что превращение его в' set' намного эффективнее ('x in s' является O (1) для наборов, O (n) для списков) в соответствии с http : //wiki.python.org/moin/TimeComplexity –

+0

@Downvoter: Не могли бы вы оставить комментарий о том, что было не так с этим ответом? Я бы очень хотел его улучшить. :) –

+0

Для записи я не спускал вниз. :-) –

1

или набор

set(b).difference(a) 

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

7

Что о

b= set(b) - set(a) 

Если вам нужно возможные повторы в b также повторяются в результате и/или порядке сохранения, затем

b= [ x for x in b if not x in a ] 

сделаю.

+1

Этот ответ был опущен один раз. Может кто-нибудь сказать почему? Любой серьезный синтаксис/концептуальная ошибка? Не способствуя заданному вопросу (и учитывая, что иногда очень сложно понять, что задается)? Плохой английский до непонятного? –

2

Вы попросили удалить как списки дублирует, вот мое решение:

from collections import OrderedDict 
a = ["abc", "def", "ijk", "lmn", "opq", "rst", "xyz"] 
b = ["ijk", "lmn", "opq", "rst", "123", "456", ] 

x = OrderedDict.fromkeys(a) 
y = OrderedDict.fromkeys(b) 

for k in x: 
    if k in y: 
     x.pop(k) 
     y.pop(k) 


print x.keys() 
print y.keys() 

Результат:

['abc', 'def', 'xyz'] 
['123', '456'] 

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

18

Вот что происходит. Предположим, у вас есть этот список:

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

и вы перебираете каждый элемент в списке. Предположим, что вы находитесь в настоящее время в индексном положении 1:

['a', 'b', 'c', 'd'] 
    ^
     | 
    index = 1 

...и удалить элемент в позиции с индексом 1, что дает вам это:

['a',  'c', 'd'] 
    ^
     | 
    index 1 

После удаления элемента, другие элементы скольжения влево, давая вам это:

['a', 'c', 'd'] 
    ^
     | 
    index 1 

Затем, когда запускает цикл опять же, цикл увеличивает индекс 2, что дает вам это:

['a', 'c', 'd'] 
      ^
      | 
     index = 2 

Посмотрите, как вы перепрыгнуть «с»? Урок: никогда не удаляйте элемент из списка, который вы зацикливаете.

+4

Этот ответ содержит совершенно четкое объяснение причины проблемы, я не понимаю, почему он получил отрицательный голос. – Bart

+0

Да, вы правы. Надеюсь, это ошибка, которая не может быть исправлена, потому что downvotes заблокированы один раз. –

+0

Возможно, причиной для downvotes является отсутствие рабочего решения ... –

1

Один из способов избежать проблем редактирования списка в то время как вы итерация над ним, заключается в использовании постижений:

a = ["abc", "def", "ijk", "lmn", "opq", "rst", "xyz"] 
b = ["ijk", "lmn", "opq", "rst", "123", "456", ] 
b = [x for x in b if not x in a] 
+0

То же решение, отправленное 1 час назад Mario Rossi и Sukrit Kalra. –

+0

Возможно, Маймер Пател начал писать его в то же время, что и я. Это тема для мета (я думаю): либо блокирование вопросов, когда 1 (или, возможно, 2) люди отвечают им (на определенное количество времени?), Или, по крайней мере, указывают на то, сколько других людей отвечает на них. Я имею в виду, прежде чем ответы ** отправлены **. Но я нобе. Если что-то вроде этого уже есть, сообщите мне. –

0

Есть уже много ответов на вопрос «как вы можете это исправить?», Так что это «как вы можете улучшить его и быть более вещим?»: так что вы хотите достичь, чтобы получить разницу между списком b и списком a, вы должны использовать операцию разности на множествах (operations on sets):

>>> a = ["abc", "def", "ijk", "lmn", "opq", "rst", "xyz"] 
>>> b = ["ijk", "lmn", "opq", "rst", "123", "456", ] 
>>> s1 = set(a) 
>>> s2 = set(b) 
>>> s2 - s1 
set(['123', '456']) 
Смежные вопросы