用Python筛选列表,然后取消筛选

用Python筛选列表,然后取消筛选,python,Python,我有一个Python的项目列表(v2.7,但是v2/v3兼容的解决方案会更好),例如: 我想过滤掉None值,然后对结果列表进行处理,例如: b = [x for x in a if x is not None] c = f(b) 然后我想把None值放回它们原来的索引中: d = # ??? should give me [c[0],c[1],c[2],None,c[3],None,None,c[4]] 我需要立即将整个筛选列表传递给函数f()。我想知道是否有一个优雅的方式来做到这一点,因

我有一个Python的项目列表(v2.7,但是v2/v3兼容的解决方案会更好),例如:

我想过滤掉None值,然后对结果列表进行处理,例如:

b = [x for x in a if x is not None]
c = f(b)
然后我想把None值放回它们原来的索引中:

d = # ??? should give me [c[0],c[1],c[2],None,c[3],None,None,c[4]]
我需要立即将整个筛选列表传递给函数f()。我想知道是否有一个优雅的方式来做到这一点,因为我所有的解决方案到目前为止都是混乱的。这是我迄今为止最干净的一个:

d = c
for i in range(len(a)):
    if not a[i]:
        d.insert(i, None)

编辑:修复列表理解中的打字错误。

让我们尝试跟踪非
的位置:

j = 0
d = []
for x in a:
    if x is None:
        d.append(None)
    else:
        d.append(c[j])
        j=j+1
>>> def f(seq):
...     return [x+x for x in seq]
>>> a = [1,6,5,None,5,None,None,1]
>>> indices, filtered = zip(*[(i, v) for i,v in enumerate(a) if v is not None])
>>> indices
(0, 1, 2, 4, 7)
如前所述:

>>> filtered
(1, 6, 5, 5, 1)
>>> mapped = f(filtered)
>>> mapped
[2, 12, 10, 10, 2]
从这里,我们可以从索引及其相应输出中创建一个“稀疏”列表:

>>> unfiltered = dict(zip(indices, mapped))
>>> unfiltered
{0: 2, 1: 12, 2: 10, 4: 10, 7: 2}
然后我们可以通过检查每个索引位置将其扩展为非稀疏版本:

>>> result = [unfiltered.get(i) for i in range(len(a))]
>>> result
[2, 12, 10, None, 10, None, None, 2]

下面是一个简单的解决方案,似乎可以做到这一点:

>>> a = [1,6,5,None,5,None,None,1]
>>> b = [x for x in a if x is not None]
>>> c = [2,12,10,10,2]  # just an example
>>> 
>>> v = iter(c)
>>> [None if x is None else next(v) for x in a]
[2, 12, 10, None, 10, None, None, 2]

可以重构
f(b)
以接受
b
的单个元素,从而
f(b)==[f(x)表示b中的x]
?如果是这样,我发布的答案(可以取消删除)将是合理的。否则,我认为您需要缓存非None元素的位置,以便在处理后可以将新值重新分配给列表。@g.d.d.c:不幸的是,函数f()需要立即接受整个列表(我使用grequests在f()中并行处理事情)。注意:由于您不复制(
d=c
),因此,你同时在修改
c
。我想你的意思是“如果x不是无的话”@Istvan Chung:是的okay@woot好吧,原来问题的例子也一样,所以可能没什么关系。@woot,当然,但c看起来只是暂时用的。@IstvanChung它是,但我打赌这是无意的,因为他费心设置d。这实际上与我的解决方案非常相似,除了(1)
如果x不是其他的话,则无…
是我使用的,因为你已经知道
x
在那一点上是
无的,并且(2)我使用迭代器在
c
上迭代,重复弹出前面的元素不会导致性能差(请记住,
lst.pop(0)
在列表长度上是一个O(n)操作)。同意-我喜欢这个解决方案,比我在最初的帖子中更喜欢,但不把c放在前面看起来更干净。很好,这在一行中运行。修复b,即使他把如果a不是无,我想他的意思是如果x不是无。@woot谢谢,我修复了它。很好-比我上面的解决方案干净多了。谢谢
>>> result = [unfiltered.get(i) for i in range(len(a))]
>>> result
[2, 12, 10, None, 10, None, None, 2]
>>> a = [1,6,5,None,5,None,None,1]
>>> b = [x for x in a if x is not None]
>>> c = [2,12,10,10,2]  # just an example
>>> 
>>> v = iter(c)
>>> [None if x is None else next(v) for x in a]
[2, 12, 10, None, 10, None, None, 2]