И б. Я хочу удалить все числа в списке b, где есть '0', а также соответствующие числа в a, которые имеют тот же индекс с нулями в b. Это мой код:
a = [ 1 , 23 , 3 , 45 , 5 , 63 , 7 , 8 , 9 , 10 , 11 , 12 , 13 , 14 , 15]
b = [ 8 , 0 , 0 , 7 , 0 , 9 , 3 , 2 , 4 , 13 , 25 , 45 , 34 , 25 , 11]
indexzeroes = [i for i, j in enumerate(b) if j == 0]
for i in indexzeroes:
b.pop(i)
a.pop(i)
print a
print b
Однако я получаю неправильные обновленные списки для a и b. Я определил причину, заключающуюся в том, что в цикле «for» я менял структуру списка каждый раз, когда «выталкивал» элемент, так что меняются и индексы с остальными нулями.
Это кажется настолько запутанным для такой якобы простой проблемы. Кто-нибудь может помочь?
3 ответа
Причина в том, что когда вы pop
i
-й индекс из a
или b
, все элементы сдвигаются влево один раз. Вы можете решить это, вставив элементы в обратном порядке (поскольку индексы должны быть в отсортированном порядке):
for i in reversed(indexzeroes):
a.pop(i)
b.pop(i)
С учетом сказанного, это, вероятно, несколько неэффективно для больших списков (наихудший случай O (n ^ 2)). Вам лучше использовать set
, который даст вам алгоритм O(n)
за счет небольшой дополнительной памяти:
indexzeroes = {i for i, j in enumerate(b) if j == 0}
a = [x for i, x in enumerate(a) if i not in indexzeros]
b = [x for i, x in enumerate(b) if i not in indexzeros]
В качестве альтернативного подхода, вы могли бы использовать понимание списка следующим образом:
a = [1, 23, 3, 45, 5, 63, 7, 8, 9, 10, 11, 12, 13, 14, 15]
b = [8, 0 , 0, 7 , 0, 9 , 3, 2, 4, 13, 25, 45, 34, 25, 11]
a_out = []
b_out = []
[(a_out.append(v1), b_out.append(v2)) for v1, v2 in zip(a,b) if v2]
print a_out
print b_out
Это будет отображать следующее:
[1, 45, 63, 7, 8, 9, 10, 11, 12, 13, 14, 15]
[8, 7, 9, 3, 2, 4, 13, 25, 45, 34, 25, 11]
Если списки велики, вы также можете переключиться на использование itertools.izip
вместо zip
.
Или как предложено, используя ваниль for-loop
:
a = [1, 23, 3, 45, 5, 63, 7, 8, 9, 10, 11, 12, 13, 14, 15]
b = [8, 0 , 0, 7 , 0, 9 , 3, 2, 4, 13, 25, 45, 34, 25, 11]
a_out = []
b_out = []
for v1, v2 in zip(a,b):
if v2:
a_out.append(v1)
b_out.append(v2)
print a_out
print b_out
Вы можете удалить, если вы начинаете с конца списков:
for ind in range(len(a) - 1, -1, -1):
if b[ind] == 0:
del a[ind]
del b[ind]
Выход:
[1, 45, 63, 7, 8, 9, 10, 11, 12, 13, 14, 15]
[8, 7, 9, 3, 2, 4, 13, 25, 45, 34, 25, 11]
Начиная с конца работает, так как списки становятся меньше, поэтому любой элемент, который мы еще не видели, будет по-прежнему с тем же индексом, что и индекс меньше, чем все, что мы видели до сих пор. Вы также должны действительно использовать list.pop
, только если вы хотите использовать возвращаемый элемент, если вы просто хотите удалить, то list.remove
или del
, как указано выше, будет лучшим.
Вы также можете сделать это за O(n)
время с помощью набора, создав новые списки:
a = [1, 23, 3, 45, 5, 63, 7, 8, 9, 10, 11, 12, 13, 14, 15]
b = [8, 0, 0, 7, 0, 9, 3, 2, 4, 13, 25, 45, 34, 25, 11]
from itertools import izip
def remove_(i,l1,l2):
c,d = [], []
for j, k in izip(l1, l2):
if k != i:
c.append(j),d.append(k)
return c, d
a, b= remove_(0, a, b)
print(a,b)
Похожие вопросы
Новые вопросы
python
Python - это многопарадигмальный, динамически типизированный, многоцелевой язык программирования. Он разработан для быстрого изучения, понимания и использования, а также для обеспечения чистого и единообразного синтаксиса. Обратите внимание, что Python 2 официально не поддерживается с 01.01.2020. Тем не менее, для вопросов о Python, связанных с версией, добавьте тег [python-2.7] или [python-3.x]. При использовании варианта Python (например, Jython, PyPy) или библиотеки (например, Pandas и NumPy) включите его в теги.