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
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:]
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:]
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
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)]
5条答案
按热度按时间pepwfjgg1#
使用zip()将第二个列表视为标志
d5vmydt92#
您需要
itertools.compress
的逆函数,它可以使用内置函数构建,例如:并且对于大输入来说将是最有效的解决方案(特别是当您省略了
list
Package 而直接在compress
对象上循环时)但是这在意义上变得有点密集了,所以你可能只想把它写成
compress
等价的listcomp,调整一下测试来反转它:这两种情况都可以通过简单的切片分配来“就地”更新
list1
:如果出于某种原因,您 * 必须 * 就地 * 直接 * 移除项目(不创建新数据的临时结构,然后替换
list1
中的旧数据),您可以依次迭代输入(使用zip
,如前所述)并手动跟踪到目前为止保留的元素数量,允许您通过不执行重复的向下复制操作来保留工作O(n)
,将元素的实际删除推迟到最后,因此list
实际上仅调整大小(至多)一次:在线试用!
这是可能的算法效率最高的完全就地解决方案(不涉及临时
list
或其他O(n)
存储要求),但它是最复杂的,在CPython参考解释器上可能比延迟原地解决方案慢,这仅仅是因为它在Python层做了更多的工作,而没有字节码解释器的直接支持(简单的整数运算是CPython的开销与完成的工作量之比最差的事情之一,至少在Python 3.11之前,他们为它添加了一些优化)。从好的方面来看,它在内存方面非常好,因为逐段向下复制会将较早的元素替换为较晚元素的别名,可能会在执行过程中清除内存(只有当被替换的元素很大且没有在其他地方使用别名,但仍有意义时才有意义)。您可以通过None
-ing来更快地释放内存:但这不太可能有帮助你最终会做更多的工作(跟踪索引和显式地
None
出你没有保留的东西),只是为了更快地释放内存。为了进行性能比较,一些IPython微基准测试基于以下版本(所有版本均在CPython 3.10.5、x86-64和Linux上运行):
时间:
正如预期的那样,在CPython中使用将所有工作推到C层的工具(
compress
,map
+not_
,片分配)是最快的,它们受益于专用字节码(listcomp)和 * 一些 * C级别改进(从list
到list
的切片赋值)都要慢一点,而那些在Python层完成几乎所有工作的是最慢的(而且做的越多,速度就越慢)。yhuiod9q3#
zhte4eai4#
结果:
vsdwdz235#
你可以使用列表解析来创建一个新的列表,其中只包含list1中与list2中的0相对应的元素。
这将并行迭代两个列表,对于每一对元素(x,y)和z,如果z等于0,它将把元素对(x,y)添加到结果列表中。
例如,给定您提供的列表list1和list2: