问题描述
我想用先前的变量(对于所有连续的None)替换None
中的list
。我是用if
和for
(多行)完成的。有没有办法在一行中做到这一点?即列表理解,Lambda和或地图
我的想法是使用列表推导,但是我无法在列表推导中分配变量来设置先前的值。
我的项目中有一个类似的场景,以这种方式处理None
,但事实是,我不想为这种小功能编写10行代码。
def none_replace(ls):
ret = []
prev_val = None
for i in ls:
if i:
prev_val = i
ret.append(i)
else:
ret.append(prev_val)
return ret
print('Replaced None List:',none_replace([None,None,1,2,3,4,5,None]))
输出:
Replaced None List: [None,5]
解决方法
在Python 3.8或更高版本中,您可以使用assignment operator:
def none_replace(ls):
p = None
return [p:=e if e is not None else p for e in ls]
,
您可以利用列表的可变性
x =[None,None,1,2,3,4,5,None]
for i,e in enumerate(x[:-1],1):
if x[i] is None:
x[i] = x[i-1]
print(x)
输出
[None,5]
,
您可以使用函数accumulate()
和运算符or
:
from itertools import accumulate
list(accumulate(lst,lambda x,y: y or x))
# [None,5]
在此解决方案中,您将元素y
和上一个元素x
并使用运算符or
进行比较。如果y
是None
,则取上一个元素x
; otherweise,您取y
。如果两者均为None
,您将得到None
。
有没有办法在一行中完成此操作?即列表理解,Lambda和或地图
由于the late binding closures,我不这样认为。此外,它可能不可读。
我的项目中有一个类似的场景,以这种方式处理None,但事实是我不想为这种小功能编写10行代码。
您为什么认为它很小?问题是需要解决的问题。一个小功能听起来像是解决它的不错选择。
我的解决方法:
def none_replace(ls: list):
prev,this = ls[0],None
assert prev is not None,"First arg can't be None"
for i in range(1,len(ls)):
this = ls[i]
if this is None:
ls[i] = prev
prev = this or ls[i]
return ls
print('Replaced None List:',none_replace(['asd',None]))
,
仅出于完整性考虑,这是适用于Python
[
x.__setitem__(i,e if e is not None else x[i-1] if i > 0 else None)
or x[i]
for i,e in enumerate(x)
]
我不得不将其分成几行以在此处显示,这可能已经表明这太可怕了,不应该使用。
list.__setitem__
返回None
,所以我使用or
总是返回列表中该位置(or x[i]
)中的当前内容。作为副作用,list.__setitem__
将第i个元素设置为自身(如果不为None),否则将其设置为先前的值(如果i
不为0,否则为None
)。
类似于我们朋友的解决方案之一。略作修改以提高可读性。代替枚举,使用range(len())
x =[None,None]
for i in range(len(x)):
if x[i] is None:
x[i] = x[i-1]
print(x)
输出: [None,5]
对于第一个值x [-1]到None
值。因此执行程序时没有错误...
反馈总是值得赞赏的..:)
,for i in range(len(ls)):
if ls[i] is None:
ls[i] = ls[i-1]
如果它是None,它将设置为上一个变量。
,您可以使用生成器生成适当的值。简单来说,生成器是生成值序列并保持其最后状态的函数。调用生成器时,它们将从上次调用继续。我们利用此特性来访问列表中最后访问的项目。请查看以下代码:
L=[None,None]
def replaceNoneGenerator(L):
prev_val=None;
for item in L:
prev_val=prev_val if item is None else item
yield prev_val
L1=[item for item in replaceNoneGenerator(L)]
print(L1)
输出:[None,5]
a = [1,None]
print([a[x] if a[x] else a[x-1] for x in range(len(a))])
这绝对忽略了 None
出现在列表第一个位置但随后处理它也不应该是一项艰巨任务的情况。
尝试将这段代码与用户输入一起使用,不知何故,逻辑对硬编码列表输入工作正常,但不适用于以下输入。有关如何解决此问题的任何想法?
def ReplaceNone(ls):
t = None
list_new=[]
for i in ls:
if i is not None:
list_new.append(i)
t = i
else:
list_new.append(t)
return list_new
list = input("Enter elements seperated by comma:")
list_input = list.split(",")
print(ReplaceNone(list_input))