Как удалить конкретный элемент из массива, используя python

138

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

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

Я на самом деле хотел бы использовать структуру цикла for, потому что мне нужно использовать тот же индекс и для других массивов.

Вот код, который у меня есть:

for index, item in emails:
    if emails[index] == 'something@something.com':
         emails.pop(index)
         otherarray.pop(index)
locoboy
источник
6
Вы ищете list.remove(x)?
Джейкоб
не совсем. я хотел бы использовать цикл for, чтобы я мог повторно использовать индекс
locoboy
4
Вы не должны изменять список во время перебора.
Джейкоб
почему я не должен это делать? также это не работает для меня.
locoboy
5
Взгляните на это: не
Иаков

Ответы:

200

Вам не нужно перебирать массив. Просто:

>>> x = ['ala@ala.com', 'bala@bala.com']
>>> x
['ala@ala.com', 'bala@bala.com']
>>> x.remove('ala@ala.com')
>>> x
['bala@bala.com']

Это удалит первый случай, соответствующий строке.

РЕДАКТИРОВАТЬ: После редактирования вам все равно не нужно повторять. Просто сделать:

index = initial_list.index(item1)
del initial_list[index]
del other_list[index]
Богдан
источник
1
см. выше, я хотел бы использовать цикл for для повторного использования того же индекса
locoboy
Отредактировал мой ответ. Все еще нет необходимости в петле.
Богдан
1
Как вы сначала проверяете, что элемент существует в initial_list? Там может быть случай, когда он не существует, и вам не придется его удалять.
locoboy
17

Использование filter()и lambdaобеспечит аккуратный и краткий метод удаления нежелательных значений:

newEmails = list(filter(lambda x : x != 'something@something.com', emails))

Это не меняет электронные письма. Он создает новый список newEmails, содержащий только элементы, для которых анонимная функция вернула True.

Рон Калян
источник
5

Ваш цикл for неправильный, если вам нужен индекс в цикле for:

for index, item in enumerate(emails):
    # whatever (but you can't remove element while iterating)

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

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

MatthieuW
источник
4

Разумный способ сделать это состоит в том, чтобы использовать zip()и выражение списка / выражения генератора:

filtered = (
    (email, other) 
        for email, other in zip(emails, other_list) 
            if email == 'something@something.com')

new_emails, new_other_list = zip(*filtered)

Кроме того, если вы не используете array.array()или numpy.array(), то, скорее всего, вы используете []или list(), которые дают вам списки, а не массивы. Не то же самое.

pillmuncher
источник
1
Никто не уверен, насколько это «нормально» по сравнению с ответом @ Богдана, который намного, намного чище.
Джордан Лапп
Спасибо за указание, что массивы не совпадают со списками. Выбранный ответ не работает с массивами в 2.7.
EL_DON
2

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

Мы начинаем с 2 списка одинаковой длины: emails, otherarray. Цель состоит в том, чтобы удалить элементы из обоих списков для каждого индекса, iгде emails[i] == 'something@something.com'.

Это может быть достигнуто с помощью понимания списка, а затем разделения через zip:

emails = ['abc@def.com', 'something@something.com', 'ghi@jkl.com']
otherarray = ['some', 'other', 'details']

from operator import itemgetter

res = [(i, j) for i, j in zip(emails, otherarray) if i!= 'something@something.com']
emails, otherarray = map(list, map(itemgetter(0, 1), zip(*res)))

print(emails)      # ['abc@def.com', 'ghi@jkl.com']
print(otherarray)  # ['some', 'details']
JPP
источник