Удаление элементов списка на основе условия

#python #list #elements

#python

Вопрос:

У меня есть список списков: [word, good freq, bad freq, change_status]

 list_1 = [['good',100, 20, 0.2],['bad', 10, 0, 0.0],['change', 1, 2, 2]]
  

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

Итак, если change_status > 0.3 and bad_freq < 5 тогда я хотел бы удалить соответствующие ему элементы.

Таким образом, list_1 будет изменен как,

 list_1 = [['good',100, 20, 0.2],['bad', 10, 0, 0.0]]
  

Как мне выборочно это сделать?

Комментарии:

1. Я думаю, он имел > в виду первое. Но на самом деле ваш комментарий неверен. x < a и x < b с a < b результатами в x < a , а не в x < b , как вы сказали.

2. Я получаю good , а change не good и bad для этих условий — bad s bad_freq есть 0 и его change_status есть 0.0 .

Ответ №1:

 list_1 = [['good',100, 20, 0.2],['bad', 10, 0, 0.0],['change', 1, 2, 2]]
list_1 = [item for item in list_1 if item[2] >= 5 or item[3] >= 0.3]
  

Вы также можете использовать if not (item[2] < 5 and item[3] < 0.3) для условия, если хотите.

Комментарии:

1. Гораздо более pythonic, чем filter с a lambda .

2. @savinos Смотрите Мои комментарии к ответу ThiefMaster. Понимание списков обычно считается более питоническим, особенно когда map или filter потребует lambda , а не просто встроенного.

3. Разве это не создает новый список? Есть ли способ сделать это на месте?

4. @SreenikethanI Вы можете, если вручную присвоите элементам их новые индексы в списке, а затем сократите его до новой длины. Но в целом это будет намного медленнее, чем это (если время, которое требуется, вообще значительно), и список должен быть очень большим, чтобы использование памяти было значительным, поскольку оно содержит только ссылки.

5. @SreenikethanI def shrink(lst): new = 0 for item in lst: if item % 2: # example condition lst[new] = item new = 1 lst[new:] = []

Ответ №2:

Используйте filter функцию с соответствующей функцией.

 list_1 = filter(lambda x: x[3] <= 0.3 and x[2] < 5, list_1)
  

ДЕМОНСТРАЦИЯ:

 In [1]: list_1 = [['good',100, 20, 0.2],['bad', 10, 0, 0.0],['change', 1, 2, 2]]
In [2]: filter(lambda x: x[3] <= 0.3 and x[2] < 5, list_1)
Out[2]: [['bad', 10, 0, 0.0]]
  

Обратите внимание, что good не удовлетворяет вашему условию ( 20 < 5 равно false), хотя вы так сказали в своем вопросе!


Если у вас много элементов, вы можете использовать эквивалентную функцию из itertools:

 from itertools import ifilter
filtered = ifilter(lambda x: x[3] <= 0.3 and x[2] < 5, list_1)
  

Комментарии:

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

2. «и использовать фильтр только для встроенных функций» — есть ли причина для этого?

3. Потому что понимание списка читается лучше, чем фильтр для лямбда-выражения, а также, как правило, работает лучше. Накладные расходы на лямбда-выражение довольно высоки. Если производительность имеет значение, и есть соответствующий встроенный (часто из модуля operator), то фильтрация по встроенному иногда может быть быстрее, чем эквивалентное понимание списка.

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

5. itertools.ifilter() был удален в Python 3 , поскольку встроенная filter() функция теперь предоставляет ту же функциональность.