复制非零值列表以填充另一个列表的零的Pythonic方法

复制非零值列表以填充另一个列表的零的Pythonic方法,python,list,Python,List,这是我想放入另一个列表中的数字列表,替换所有零值 a = [2, 5, 6, 3, 9] b = [0, 7, 9, 3, 3, 0, 4, 0, 3, 1, 0, 0, 4] 下面是替换所有零值之前其他列表的外观 a = [2, 5, 6, 3, 9] b = [0, 7, 9, 3, 3, 0, 4, 0, 3, 1, 0, 0, 4] 这样c将 c = [[2, 3, 9, 1, 3] [3, 3, 4, 2, 5] [3, 5, 5, 6, 2] [3,

这是我想放入另一个列表中的数字列表,替换所有零值

a = [2, 5, 6, 3, 9]
b = [0, 7, 9, 3, 3, 0, 4, 0, 3, 1, 0, 0, 4] 下面是替换所有零值之前其他列表的外观

a = [2, 5, 6, 3, 9]
b = [0, 7, 9, 3, 3, 0, 4, 0, 3, 1, 0, 0, 4] 这样
c

c = [[2, 3, 9, 1, 3]
     [3, 3, 4, 2, 5]
     [3, 5, 5, 6, 2]
     [3, 9, 3, 8, 9]
     [1, 2, 3, 4, 5]]

一种方法是使用
iter
创建一个对象,逐个给出
a
中的每个元素,然后使用普通的listcomp:

>>> a = [2, 5, 6, 3, 9]
>>> b = [0, 7, 9, 3, 3, 0, 4, 0, 3, 1, 0, 0, 4]
>>> fill = iter(a)
>>> c = [x if x != 0 else next(fill) for x in b]
>>> c
[2, 7, 9, 3, 3, 5, 4, 6, 3, 1, 3, 9, 4]
>>> fill = iter(a)
>>> b = [[0, 3, 9, 1, 3], [3, 3, 4, 2, 0], [3, 5, 5, 0, 2], [0, 0, 3, 8, 9], [1, 2, 3, 4, 5]]
>>> c = [[x if x != 0 else next(fill) for x in row] for row in b]
>>> c
[[2, 3, 9, 1, 3], [3, 3, 4, 2, 5], [3, 5, 5, 6, 2], [3, 9, 3, 8, 9], [1, 2, 3, 4, 5]]
正如@bulbus所指出的,如果没有足够的零来填充,这将引发StopIteration异常。您可以使用
next
的默认值,例如
next(fill,0)
,如果您想避免这种情况

对于您的2D案例,同样的方法也适用,我们只需要更改listcomp:

>>> a = [2, 5, 6, 3, 9]
>>> b = [0, 7, 9, 3, 3, 0, 4, 0, 3, 1, 0, 0, 4]
>>> fill = iter(a)
>>> c = [x if x != 0 else next(fill) for x in b]
>>> c
[2, 7, 9, 3, 3, 5, 4, 6, 3, 1, 3, 9, 4]
>>> fill = iter(a)
>>> b = [[0, 3, 9, 1, 3], [3, 3, 4, 2, 0], [3, 5, 5, 0, 2], [0, 0, 3, 8, 9], [1, 2, 3, 4, 5]]
>>> c = [[x if x != 0 else next(fill) for x in row] for row in b]
>>> c
[[2, 3, 9, 1, 3], [3, 3, 4, 2, 5], [3, 5, 5, 6, 2], [3, 9, 3, 8, 9], [1, 2, 3, 4, 5]]

我相信在这种情况下,最简单、可读性最好的方法是:

a = [2, 5, 6, 3, 9]
b = [0, 7, 9, 3, 3, 0, 4, 0, 3, 1, 0, 0, 4]
new_list = []
count = 0
for i in b:
    if i == 0:
       new_list.append(a[count])
       count += 1
    else:
       new_list.append(i)
输出:

[2, 7, 9, 3, 3, 5, 4, 6, 3, 1, 3, 9, 4]

首先,让我们确保您的
a
系列足够长:

a_long = itertools.chain(a, itertools.repeat(0))
这将在耗尽原始
a
后提供无尽的零

然后,我们将为该系列创建一个迭代器,以便有选择地提取
next()
值:

a_iter = iter(a_long)
最后,使用
a
系列的替换项生成
b
,只要它们可用:

result = (bval if bval != 0 else next(a_iter) for bval in b)
结果:

>>> a = [2, 5, 6, 3, 9]
>>> b = [0, 7, 9, 3, 3, 0, 4, 0, 3, 1, 0, 0, 4, 0, 1, 0, 2]

>>> import itertools
>>> a_long = itertools.chain(a, itertools.repeat(0))
>>> a_iter = iter(a_long)

>>> result = (bval if bval != 0 else next(a_iter) for bval in b)
>>> result
<generator object <genexpr> at 0x10aab1af0>
>>> list(result)
>>> [2, 7, 9, 3, 3, 5, 4, 6, 3, 1, 3, 9, 4, 0, 1, 0, 2]
a=[2,5,6,3,9] >>>b=[0,7,9,3,3,0,4,0,3,1,0,0,4,0,1,0,2] >>>进口itertools >>>a_long=itertools.chain(a,itertools.repeat(0)) >>>国际热核聚变实验堆=国际热核聚变实验堆(长) >>>结果=(如果bval!=0,则bval!=下一个(a_iter)对于b中的bval) >>>结果 >>>名单(结果) >>> [2, 7, 9, 3, 3, 5, 4, 6, 3, 1, 3, 9, 4, 0, 1, 0, 2]
请注意,所有中间值(a_long,a_iter)都是可迭代的,因此它们可以处理超长系列而无需大量内存分配。结果是一个生成器,因此它一次只保留一个值。

您可以使用numpy在适当的位置修改
b
(或者先将
b
复制到
c
,然后如果希望在
c
中修改
c
):

然后直接将
a
的元素依次分配给
b
中的每个元素,其中
0

>>> b[b==0]=a     # len(a)>=the number of 0's in this case...
或者,构建
a
元素列表或默认值:

>>> b[b==0]=a+[0]*(np.count_nonzero(b==0)-len(a))
               ^             0 used as default for elements not found in a
vals=iter(a)
for t in zip(*np.where(b==0)):
    b[t]=next(vals, 0)  
或者,您可以循环索引元组,其中
b
为0,并指定
a
中的下一个值或默认值:

>>> b[b==0]=a+[0]*(np.count_nonzero(b==0)-len(a))
               ^             0 used as default for elements not found in a
vals=iter(a)
for t in zip(*np.where(b==0)):
    b[t]=next(vals, 0)  

如果零太多,此操作将失败
[x if x!=0 else next(fill,0)表示b中的x]
@bulbus:我倾向于选择错误而不是静默扩展,但你是对的,有些人感觉不一样。