删除python中的相应列表

tquggr8v  于 2022-12-17  发布在  Python
关注(0)|答案(5)|浏览(106)

我有一个这样的列表:[(10,2),(5,3),(15,5),(7,7),(6,1),(18,4),(3,1)]和另一个列表如下:[1, 1, 1, 0, 1, 1, 0]现在我想从第一个列表中删除所有项目,其中第二个列表项目值为1。

list1 = [(10,2),(5,3),(15,5),(7,7),(6,1),(18,4),(3,1)]
list2 = [1, 1, 1, 0, 1, 1, 0]

最终结果应为:[(7,7), (3,1)]
我该怎么做呢?

pepwfjgg

pepwfjgg1#

使用zip()将第二个列表视为标志

>>> list1 = [(10,2), (5,3), (15,5), (7,7), (6,1), (18,4), (3,1)]
>>> list2 = [1, 1, 1, 0, 1, 1, 0]

>>> rst = [item for item, flag in zip(list1, list2) if not flag]
>>> rst 
[(7, 7), (3, 1)]
d5vmydt9

d5vmydt92#

您需要itertools.compress的逆函数,它可以使用内置函数构建,例如:

from itertools import compress
from operator import not_

list3 = list(compress(list1, map(not_, list2)))

并且对于大输入来说将是最有效的解决方案(特别是当您省略了list Package 而直接在compress对象上循环时)
但是这在意义上变得有点密集了,所以你可能只想把它写成compress等价的listcomp,调整一下测试来反转它:

list3 = [val for val, selector in zip(list1, list2) if not selector]

这两种情况都可以通过简单的切片分配来“就地”更新list1

list1[:] = compress(list1, map(not_, list2))
# or
list1[:] = [val for val, selector in zip(list1, list2) if not selector]

如果出于某种原因,您 * 必须 * 就地 * 直接 * 移除项目(不创建新数据的临时结构,然后替换list1中的旧数据),您可以依次迭代输入(使用zip,如前所述)并手动跟踪到目前为止保留的元素数量,允许您通过不执行重复的向下复制操作来保留工作O(n),将元素的实际删除推迟到最后,因此list实际上仅调整大小(至多)一次:

kept_count = 0
for val, selector in zip(list1, list2):
    if not selector:
        list1[kept_count] = val  # Move an alias to the element to its new position
        kept_count +=1  # We kept another element, track that
del list1[kept_count:]  # Bulk delete all elements after those kept

在线试用!
这是可能的算法效率最高的完全就地解决方案(不涉及临时list或其他O(n)存储要求),但它是最复杂的,在CPython参考解释器上可能比延迟原地解决方案慢,这仅仅是因为它在Python层做了更多的工作,而没有字节码解释器的直接支持(简单的整数运算是CPython的开销与完成的工作量之比最差的事情之一,至少在Python 3.11之前,他们为它添加了一些优化)。从好的方面来看,它在内存方面非常好,因为逐段向下复制会将较早的元素替换为较晚元素的别名,可能会在执行过程中清除内存(只有当被替换的元素很大且没有在其他地方使用别名,但仍有意义时才有意义)。您可以通过None-ing来更快地释放内存:

kept_count = 0
for i, (val, selector) in enumerate(zip(list1, list2)):  # Track current index
    if not selector:
        list1[kept_count] = val
        kept_count +=1
    else:
        list1[i] = None  # Eagerly clear references to elements we're not keeping
del list1[kept_count:]

但这不太可能有帮助你最终会做更多的工作(跟踪索引和显式地None出你没有保留的东西),只是为了更快地释放内存。
为了进行性能比较,一些IPython微基准测试基于以下版本(所有版本均在CPython 3.10.5、x86-64和Linux上运行):

from itertools import compress
from operator import not_

def cutdown1(lst, selectors):
    lst[:] = compress(lst, map(not_, selectors))

def cutdown2(lst, selectors):
    lst[:] = [val for val, selector in zip(lst, selectors) if not selector]

def cutdown3(lst, selectors):
    kept_count = 0
    for val, selector in zip(lst, selectors):
        if not selector:
            lst[kept_count] = val
            kept_count +=1
    del lst[kept_count:]

def cutdown4(lst, selectors):
    kept_count = 0
    for i, (val, selector) in enumerate(zip(lst, selectors)):
        if not selector:
            lst[kept_count] = val
            kept_count +=1
        else:
            lst[i] = None
    del lst[kept_count:]

时间:

>>> %%timeit list1 = [(1,2), (3,4), (5,6), (7,8), (9,10)] * 10; list2 = (1,1,0,1,0) * 10; c = cutdown1
... c(list1.copy(), list2)
...
1.36 µs ± 47.3 ns per loop (mean ± std. dev. of 7 runs, 1,000,000 loops each)

>>> %%timeit list1 = [(1,2), (3,4), (5,6), (7,8), (9,10)] * 10; list2 = (1,1,0,1,0) * 10; c = cutdown2
... c(list1.copy(), list2)
...
1.79 µs ± 80.8 ns per loop (mean ± std. dev. of 7 runs, 1,000,000 loops each)

>>> %%timeit list1 = [(1,2), (3,4), (5,6), (7,8), (9,10)] * 10; list2 = (1,1,0,1,0) * 10; c = cutdown3
... c(list1.copy(), list2)
...
2.09 µs ± 5.5 ns per loop (mean ± std. dev. of 7 runs, 100,000 loops each)

>>> %%timeit list1 = [(1,2), (3,4), (5,6), (7,8), (9,10)] * 10; list2 = (1,1,0,1,0) * 10; c = cutdown4
... c(list1.copy(), list2)
...
3.25 µs ± 53.5 ns per loop (mean ± std. dev. of 7 runs, 100,000 loops each)

正如预期的那样,在CPython中使用将所有工作推到C层的工具(compressmap + not_,片分配)是最快的,它们受益于专用字节码(listcomp)和 * 一些 * C级别改进(从listlist的切片赋值)都要慢一点,而那些在Python层完成几乎所有工作的是最慢的(而且做的越多,速度就越慢)。

yhuiod9q

yhuiod9q3#

list1 = [(10,2),(5,3),(15,5),(7,7),(6,1),(18,4),(3,1)]
list2 = [1, 1, 1, 0, 1, 1, 0]
templist=[]

if len(list1)==len(list2):
    i=0
    for index in list2:
        if index==0:
            templist.append(list1[i])
        i+=1

list1=templist
zhte4eai

zhte4eai4#

list1 = [(10, 2), (5, 3), (15, 5), (7, 7), (6, 1), (18, 4), (3, 1)]
list2 = [1, 1, 1, 0, 1, 1, 0]

removed = 0
for i in range(len(list2)):
    if list2[i]:
        del list1[i - removed]
        removed += 1

print(list1)

结果:

[(7, 7), (3, 1)]
vsdwdz23

vsdwdz235#

你可以使用列表解析来创建一个新的列表,其中只包含list1中与list2中的0相对应的元素。

result = [(x, y) for (x, y), z in zip(list1, list2) if z == 0]

这将并行迭代两个列表,对于每一对元素(x,y)和z,如果z等于0,它将把元素对(x,y)添加到结果列表中。
例如,给定您提供的列表list1和list2:

list1 = [(10,2),(5,3),(15,5),(7,7),(6,1),(18,4),(3,1)]
list2 = [1, 1, 1, 0, 1, 1, 0]

result = [(x, y) for (x, y), z in zip(list1, list2) if z == 0]

print(result)  # prints [(7,7), (3,1)]

相关问题