Вычитание одного списка из другого в python, где могут встречаться повторяющиеся значения - PullRequest
0 голосов
/ 01 мая 2019

Я ищу, чтобы удалить содержимое одного массива из другого.

array_2 = ['one' , "two" , "one", "three", "four"]
array_1 = ['one', "two"]

Моей первой мыслью было использование списка понимания

array_3 = [x for x in array_2 if x not in array_1]

Однако это приведет к удалению дублирующегося результата элемента: ['three', 'four']

Я хочу удалить "one" только один раз из массива, так как я ищу вычитание списка.Поэтому я хочу, чтобы результат был: ['one', 'three', 'four'].

Какой хороший питонический способ для достижения этой цели?

Ответы [ 5 ]

2 голосов
/ 01 мая 2019

Попробуйте Counter из collections:

from collections import Counter

array_2 = ['one' , "two" , "one", "three", "four"]
array_1 = ['one', "two"]

list((Counter(array_2) - Counter(array_1)).elements())

вывод

['one', 'three', 'four']
1 голос
/ 01 мая 2019

Вы можете использовать remove метод списка:

array_2 = ['one' , "two" , "one", "three", "four"]
array_1 = ['one', "two"]

# copy list
array_3 = array_2[:]

for element in array_1:
    try:
        array_3.remove(element)
    except ValueError:
        pass
print(array_3)
# ['one', 'three', 'four']
0 голосов
/ 01 мая 2019

Я просто собираю превосходные решения, уже приведенные выше.

Если вы заботитесь о поддержании первоначального порядка, в котором были элементы в array_2, то я думаю, что вы должны использовать remove:

array_1 = ['one', 'two']
array_2 = ['one', 'two', 'one', 'three', 'four']
array_3 = list(array_2)
for x in array_1:
    try:
        array_3.remove(x)
    except ValueError:
        pass
print(array_3)

Если не имеет значения, каков окончательный порядок элементов, тогда использование Counter гораздо эффективнее, поскольку оно зацикливается на обоих списках только один раз:

from collections import Counter

array_1 = ['one', 'two']
array_2 = ['one', 'two', 'one', 'three', 'four']
array_3 = list((Counter(array_2) - Counter(array_1)).elements())
print(array_3)
0 голосов
/ 01 мая 2019

Использование функции map в сочетании с lambda решит вашу задачу:

map(lambda x: array_2.remove(x) if x in array_2 else None, array_1)

Это изменит array_2 напрямую, и результат будет:

print(array_2)
# ['one', 'three', 'four']
0 голосов
/ 01 мая 2019

Объект Counter идеально подходит для этого.

In [1]: from collections import Counter                                                                                                                                      

In [2]: array_2 = ['one' , "two" , "one", "three", "four"]                                                                                                                   

In [3]: array_1 = ['one', "two"]                                                                                                                                             

In [4]: a2 = Counter(array_2)                                                                                                                                                

In [5]: a1 = Counter(array_1)                                                                                                                                                

In [6]: a2 - a1                                                                                                                                                              
Out[6]: Counter({'one': 1, 'three': 1, 'four': 1})

Если вы хотите список, вы можете сгладить Counter, используя:

In [7]: list((a2-a1).elements())                                                                                                                                             
Out[7]: ['one', 'three', 'four']
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...