给出了一个点列表(通过路径算法找到),我对域的进入/退出点感兴趣。域外的点列为 None
。示例路径为 [None, 1, 2, None, 3, 4, 5, None]
,结果应为 [(1,2), (3,5 )]
。现在对于边缘情况 [1, 2, None]
,结果应该是 [(None, 2)]
,对于镜像情况 [None, 1 , 2]
,应该是[(1, None)]
。
没有最后两个加法,我有
[(systems[0], systems[-1]) if not outside else None
for outside, systems in [(o, list(sys))
for o, sys in groupby(path, lambda x: x is None)]]
或via IRC :
def find_borders(L):
it = iter(L)
for item in it:
if item is None:
continue
start = item
end = item
for item in it:
if item is None:
break
end = item
yield (start, end)
对于通过 IRC 的解决方案,在开始时添加 None
很容易,但如果不在 iter
上添加 peek
基本上是不可能的.
如何实现第二种边缘情况 [None, 1,2]
=> [(1, None)]
?
我创建了一个应该有效但无效的解决方案。它给了我一个 IndexError
因为 systems
是一个空列表,这不应该 发生是因为 groupby
保证它不会分组到空列表中。
def find_borders(path):
grouped = list(groupby(path, lambda x: x is None))
for index, (o, sys) in enumerate(grouped):
systems = list(sys)
if index == 0:
yield (None, systems[-1])
elif index == len(grouped)-1:
yield (systems[0], None)
else:
yield (systems[0], systems[-1])
请您参考如下方法:
tests = [
[None, 1, 2, None, 3, 4, 5, None],
[1, 2, None, 3, 4, 5, None],
[None,1, 2, None, 3, 4, 5],
[1, 2, None, 3, 4, 5],
[1, 2, None],
[None, 1, 2],
]
def find_borders(L):
it = iter(L)
start_none = False
for item in it:
if item is None:
start_none = True
continue
if start_none:
start = item
else:
start = None
end = item
end_none = False
for item in it:
if item is None:
end_none = True
break
end = item
if not end_none:
end = None
yield (start, end)
start_none = True
for t in tests:
print
print t
for x in find_borders(t):
print x
结果
[None, 1, 2, None, 3, 4, 5, None]
(1, 2)
(3, 5)
[1, 2, None, 3, 4, 5, None]
(None, 2)
(3, 5)
[None, 1, 2, None, 3, 4, 5]
(1, 2)
(3, None)
[1, 2, None, 3, 4, 5]
(None, 2)
(3, None)
[1, 2, None]
(None, 2)
[None, 1, 2]
(1, None)