Cla*_*ell 45 python null list slice
我正在寻找一种方法来轻松确定列表中的所有非None项是否出现在单个连续切片中. 我将使用整数作为非None项的示例.
例如,该列表[None, None, 1, 2, 3, None, None]
符合我对连续整数条目的要求.与此相反,[1, 2, None, None, 3, None]
是不连续的,因为有整数之间无条目.
还有一些例子可以说明这一点.
连续:
[1, 2, 3, None, None]
[None, None, 1, 2, 3]
[None, 1, 2, 3, None]
不连续:
[None, 1, None, 2, None, 3]
[None, None, 1, None, 2, 3]
[1, 2, None, 3, None, None]
我的第一种方法是使用变量来跟踪我们是否遇到了一个问题None
,以及我们是否遇到了一个问题int
- 这最终导致了一个高度嵌套且非常难以遵循的if/else系列嵌入在for循环中的语句.(除了丑陋之外,我承认在每种情况下都没有让它工作).
任何人都知道一种更简单的方法来确定列表中的非None项是否出现在单个连续切片中?
Joh*_*ooy 44
def contiguous(seq):
seq = iter(seq)
all(x is None for x in seq) # Burn through any Nones at the beginning
any(x is None for x in seq) # and the first group
return all(x is None for x in seq) # everthing else (if any) should be None.
Run Code Online (Sandbox Code Playgroud)
这里有几个例子.您可以使用next(seq)
从迭代器获取下一个项目.我会在每个之后加上一个标记指向下一个项目
例1:
seq = iter([None, 1, 2, 3, None]) # [None, 1, 2, 3, None]
# next^
all(x is None for x in seq)
# next^
any(x is None for x in seq)
# next^ (off the end)
return all(x is None for x in seq) # all returns True for the empty sequence
Run Code Online (Sandbox Code Playgroud)
例2:
seq = iter([1, 2, None, 3, None, None]) # [1, 2, None, 3, None, None]
# next^
all(x is None for x in seq)
# next^
any(x is None for x in seq)
# next^
return all(x is None for x in seq) # all returns False when 3 is encountered
Run Code Online (Sandbox Code Playgroud)
DSM*_*DSM 25
itertools.groupby
拯救的好人:
from itertools import groupby
def contiguous(seq):
return sum(1 for k,g in groupby(seq, lambda x: x is not None) if k) == 1
Run Code Online (Sandbox Code Playgroud)
给
>>> contiguous([1,2,3,None,None])
True
>>> contiguous([None, 1,2,3,None])
True
>>> contiguous([None, None, 1,2,3])
True
>>> contiguous([None, 1, None, 2,3])
False
>>> contiguous([None, None, 1, None, 2,3])
False
>>> contiguous([None, 1, None, 2, None, 3])
False
>>> contiguous([1, 2, None, 3, None, None])
False
Run Code Online (Sandbox Code Playgroud)
[编辑]
由于评论中似乎有一些讨论,我将解释为什么我比其他人更喜欢这种方法.
我们试图找出是否存在一组连续的非None对象,以及
sum(1 for k,g in groupby(seq, lambda x: x is not None) if k)
Run Code Online (Sandbox Code Playgroud)
使用stdlib中的函数计算连续的非None对象的数量,该函数用于收集连续的组.我们一看到groupby
,就会认为"连续的群体",反之亦然.从这个意义上讲,它是自我记录的.这基本上是我的目标的定义.
恕我直言唯一的弱点是它不会短路,而且可以修复,但在考虑之后我仍然更喜欢这个,因为它使用了我喜欢的原语 - "计算连续非非组的数量" - 我更喜欢"只要你能告诉我是否有一个以上的非连续非群组".
实现最后一个方法的许多方法依赖于对该问题的巧妙观察,例如"如果只有一个连续的非-Onob对象组,那么如果我们扫描直到找到第一个not-None对象,然后扫描对象直到我们找到第一个非None组(如果存在),那么剩下的是否为None给我们答案." (或类似的东西,这是我的问题的一部分:我必须考虑它.)对我来说,感觉就像使用"实现细节"解决问题,并关注我们可以用来解决的问题的属性它,而不是简单地向Python指定问题并让Python完成工作.
我是一个脑力很小的熊,正如俗话所说,我喜欢避免变得聪明,因为根据我的经验,这是一条充满失败的路线.
一如既往,每个人的里程可能会有所不同,当然,也可能与他们的聪明程度成比例.
Ble*_*der 12
你可以使用类似的东西itertools.groupby
:
from itertools import groupby
def are_continuous(items):
saw_group = False
for group, values in groupby(items, lambda i: i is not None):
if group:
if saw_group:
return False
else:
saw_group = True
return True
Run Code Online (Sandbox Code Playgroud)
这将仅迭代直到它看到一个组两次.我不确定你是否考虑[None, None]
,所以根据你的需要进行调整.
这可能不是最好的方法,但您可以查找第一个非None条目和最后一个non-None
条目,然后检查切片None
.例如:
def is_continuous(seq):
try:
first_none_pos = next(i for i,x in enumerate(seq) if x is not None)
#need the or None on the next line to handle the case where the last index is `None`.
last_none_pos = -next(i for i,x in enumerate(reversed(seq)) if x is not None) or None
except StopIteration: #list entirely of `Nones`
return False
return None not in seq[first_none_pos:last_none_pos]
assert is_continuous([1,2,3,None,None]) == True
assert is_continuous([None, 1,2,3,None]) == True
assert is_continuous([None, None, 1,2,3]) == True
assert is_continuous([None, 1, None, 2,3]) == False
assert is_continuous([None, None, 1, None, 2,3]) == False
assert is_continuous([None, 1, None, 2, None, 3]) == False
assert is_continuous([1, 2, None, 3, None, None]) == False
Run Code Online (Sandbox Code Playgroud)
这适用于任何序列类型.
使用序列元素的自然方法是使用dropwhile
:
from itertools import dropwhile
def continuous(seq):
return all(x is None for x in dropwhile(lambda x: x is not None,
dropwhile(lambda x: x is None, seq)))
Run Code Online (Sandbox Code Playgroud)
我们可以在没有嵌套函数调用的情况下表达:
from itertools import dropwhile
def continuous(seq):
core = dropwhile(lambda x: x is None, seq)
remainder = dropwhile(lambda x: x is not None, core)
return all(x is None for x in remainder)
Run Code Online (Sandbox Code Playgroud)
一个班轮:
contiguous = lambda l: ' ' not in ''.join('x '[x is None] for x in l).strip()
Run Code Online (Sandbox Code Playgroud)
真正的工作是由strip
功能完成的.如果剥离的字符串中有空格,则它们不是前导/尾随.函数的其余部分将列表转换为字符串,每个字符串都有一个空格None
.