[英]Python remove inner items of a sequence in a list
foo = [0,0,0,0,1,1,1,1,1,1,0,0,0,1,1,1,0,0,1,1]
bar = [x if x==0 else 'o' for x in foo]
酒吧:
[0, 0, 0, 0,'o', 'o', 'o', 'o', 'o', 'o', 0, 0, 0, 'o', 'o', 'o', 0, 0, 'o', 'o']
我想在此处删除内部'o',以便结果如下所示:
[0, 0, 0, 0, 'o','o', 0, 0, 0, 'o','o', 0, 0, 'o', 'o']
如果可能的话,我想在列表理解本身中这样做,并且我想避免转换为字符串的任何事情(因为我的实际任务涉及字典而不是1和0)。 有任何想法吗?
我们可以检查上一个和下一个元素,并检查它们是否也是'o'
,如果是,我们不会产生元素,否则我们会这样做,如:
nbar1 = len(bar) - 1
[ x for i, x in enumerate(bar) if not (0 < i < nbar1 and bar[i] == bar[i-1] == bar[i+1] == 'o') ]
使用chain
和zip
可以使上面更优雅:
from itertools import chain, islice
prev = chain((None,), bar)
nxt = islice(chain(bar, (None, )), 1, None)
result = [ x for p, x, n in zip(prev, bar, nxt) if not (p == x == n == 'o') ]
其中p
是“前一项”, x
是“当前项”, n
是“下一项”。
这十个产量:
>>> [ x for p, x, n in zip(prev, bar, nxt) if not (p == x == n == 'o') ]
[0, 0, 'o', 'o', 0, 0, 'o', 'o', 0, 0, 'o']
以上内容也适用于非0
秒的元素,例如:
>>> bar = [1, 3, 'o', 'o', 'o', 'o', 'o', 'o', 0, 0, 'o', 'o', 'o', 2, 0, 'o', 'o']
>>> prev = chain((None,), bar)
>>> nxt = islice(chain(bar, (None, )), 1, None)
>>> [ x for p, x, n in zip(prev, bar, nxt) if not (p == x == n == 'o') ]
[1, 3, 'o', 'o', 0, 0, 'o', 'o', 2, 0, 'o', 'o']
我们也可以轻松地将其更改为与另一个元素(而不是'o'
)一起使用,只要它不是等于None
东西。 如果是这种情况,我们可以将其他元素链接到prev
和nxt
iterables。
以上工作在线性时间O(n)中,其中n为要处理的列表的长度。
一个替代方案是使用itertools.groupby
以检测字符的“脉冲串”,并在情况下,突发包含'o'
S,我们islice(..)
最多两个元素:
来自itertools import groupby,islice
[ x for k, g in groupby(bar) for x in (islice(g, 2) if k == 'o' else g) ]
再次屈服:
>>> [ x for k, g in groupby(bar) for x in (islice(g, 2) if k == 'o' else g) ]
[0, 0, 0, 0, 'o', 'o', 0, 0, 0, 'o', 'o', 0, 0, 'o', 'o']
如果你真的想用一个理解列表来做:
bar=[x if x==0 else 'o' for i,x in enumerate(foo) if (i==0 or i==len(foo)-1) or x==0 or
foo[i-1]==0 or foo[i+1]==0]
应该适合你的榜样。
你可以做:
>>> foo = [0,0,0,0,1,1,1,1,1,1,0,0,0,1,1,1,0,0,1,1]
>>> from itertools import groupby
>>> [ext for c, grp in groupby(foo) for ext in (grp if c==0 else ['o']*min(2,len(list(grp))))]
[0, 0, 0, 0, 'o', 'o', 0, 0, 0, 'o', 'o', 0, 0, 'o', 'o']
使用itertools.groupby
如果k
为0
我们追加该组中的所有项目,如果k
为'o'
我们只追加第一个和最后一个不包括中间'o'
'的
from itertools import groupby
bar = [0, 0, 'o', 'o', 'o', 'o', 'o', 'o', 0, 0, 'o', 'o', 'o', 0, 0, 'o', 'o']
new = []
for k, g in groupby(bar):
x = list(g)
if k == 0:
for i in x:
new.append(i)
elif k == 'o':
new.append(x[0])
new.append(x[-1])
print(new)
# [0, 0, 'o', 'o', 0, 0, 'o', 'o', 0, 0, 'o', 'o']
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.