繁体   English   中英

Python删除列表中序列的内部项

[英]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') ]

使用chainzip可以使上面更优雅:

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东西。 如果是这种情况,我们可以将其他元素链接到prevnxt 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如果k0我们追加该组中的所有项目,如果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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM