Удалить элементы из списка, которые находятся в другом списке, и вернуть их индексы - PullRequest
0 голосов
/ 05 октября 2018

Это list, например:

my_list = ['a', 'd', 'a', 'd', 'c','e']
words_2_remove = ['a', 'c']

, тогда вывод должен быть:

my_list = ['d', 'd', 'e']
loc = [0, 2, 4]

Я сейчас использую это:

loc = []    
for word in my_list:  
    if word in words_2_remove:
         loc.append( my_list.index(word) )
         my_list.remove(word)

Есть ли лучшая альтернатива?

Ответы [ 3 ]

0 голосов
/ 05 октября 2018

Для больших массивов использование NumPy будет более эффективным:

import numpy as np


my_list = np.array(['a', 'd', 'a', 'd', 'c','e'])
words_2_remove = np.array(['a', 'c'])

mask = np.isin(my_list, words_2_remove, invert=True)
# mask will be [False  True False  True False  True]
loc = np.where(~mask)[0]

print(loc)
>>> [0 2 4]

print(my_list[mask])
>>> ['d' 'd' 'e']

И также довольно просто получить дополнение к индексам loc:

print(np.where(mask)[0])
>>> [1 3 5]

Сроки:
Сравнение со списком версий версии от @ Austin.
Для оригинальных массивов:

my_list = np.array(['a', 'd', 'a', 'd', 'c','e'])
words_2_remove = np.array(['a', 'c'])

%%timeit
mask = np.isin(my_list, words_2_remove, invert=True)
loc = np.where(~mask)[0]
>>> 11 µs ± 53.7 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)

my_list =['a', 'd', 'a', 'd', 'c','e']
words_2_remove = ['a', 'c']

%%timeit
loc = [i for i, x in enumerate(my_list) if x in words_2_remove]
res = [x for x in my_list if x not in words_2_remove]
>>> 1.31 µs ± 7.17 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)

И для больших массивов:

n = 10 ** 3
my_list = np.array(['a', 'd', 'a', 'd', 'c','e'] * n)
words_2_remove = np.array(['a', 'c'])

%%timeit
mask = np.isin(my_list, words_2_remove, invert=True)
loc = np.where(~mask)[0]
>>> 114 µs ± 906 ns per loop (mean ± std. dev. of 7 runs, 10000 loops each)

my_list =['a', 'd', 'a', 'd', 'c','e'] * n
words_2_remove = ['a', 'c']

%%timeit
loc = [i for i, x in enumerate(my_list) if x in words_2_remove]
res = [x for x in my_list if x not in words_2_remove]
>>> 841 µs ± 677 ns per loop (mean ± std. dev. of 7 runs, 1000 loops each)

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


Дополнительная информация:

Документы на np.isin: https://docs.scipy.org/doc/numpy-1.15.1/reference/generated/numpy.isin.html
КонвертацияМассив логических масок для индексов: Как превратить булев массив в индексный массив в numpy
Документы на np.where: https://docs.scipy.org/doc/numpy-1.13.0/reference/generated/numpy.where.html
Подробнее об индексировании с помощью NumPy: https://docs.scipy.org/doc/numpy-1.15.1/reference/arrays.indexing.html

0 голосов
/ 05 октября 2018

Использование списка и перечисление

loc = [idx for idx, item in enumerate(my_list) if item in words_2_remove]
my_list = [i for i in my_list if i not in words_2_remove]

Или использование фильтра :

my_list = list(filter(lambda x: x not in words_2_remove, my_list))

Расширенное объяснение:

loc = []
new_my_list = []
for idx, item in enumerate(my_list):
    if item in words_2_remove:
        loc.append(idx)
    else:
        new_my_list.append(item)
0 голосов
/ 05 октября 2018

Есть два списка-понимания:

my_list =['a', 'd', 'a', 'd', 'c','e']
words_2_remove = ['a', 'c']

loc = [i for i, x in enumerate(my_list) if x in words_2_remove]

my_list = [x for x in my_list if x not in words_2_remove]

print(my_list) # ['d', 'd', 'e']
print(loc)     # [0, 2, 4]
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...