简体   繁体   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]

bar: 酒吧:

[0, 0, 0, 0,'o', 'o', 'o', 'o', 'o', 'o', 0, 0, 0, 'o', 'o', 'o', 0, 0, 'o', 'o']

I would like to remove the inner 'o' at this point so that the result looks like so: 我想在此处删除内部'o',以便结果如下所示:

[0, 0, 0, 0, 'o','o', 0, 0, 0, 'o','o', 0, 0, 'o', 'o']

If possible, I'd like to do this within the list comprehension itself, and I would like to avoid anything with converting to a string (as my actual task for this involves dictionaries rather than 1's and 0's). 如果可能的话,我想在列表理解本身中这样做,并且我想避免转换为字符串的任何事情(因为我的实际任务涉及字典而不是1和0)。 Any ideas? 有任何想法吗?

By keeping track of the previous and next element 通过跟踪上一个和下一个元素

We can perform a check on the previous and next element, and check if these are 'o' s as well, if so, we do not yield the element, otherwise we do, like: 我们可以检查上一个和下一个元素,并检查它们是否也是'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') ]

The above can be made more elegant by using chain and zip : 使用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') ]

where p is the "previous item", x is the "current item", and n is the "next item". 其中p是“前一项”, x是“当前项”, n是“下一项”。

This ten yields: 这十个产量:

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

The above will also work with elements that are not 0 s, for example: 以上内容也适用于非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']

We can also easily change it to work with another element (than 'o' ), as long as it is not something that is equal to None . 我们也可以轻松地将其更改为与另一个元素(而不是'o' )一起使用,只要它不是等于None东西。 If that is the case, we can however chain other elements to the prev and nxt iterables. 如果是这种情况,我们可以将其他元素链接到prevnxt iterables。

The above works in linear time O(n) with n the length of the list to process. 以上工作在线性时间O(n)中,其中n为要处理的列表的长度。

By grouping and slicing 通过分组和切片

An alternative is to use itertools.groupby to detect "bursts" of characters, and in case the burst contains 'o' s, we islice(..) up to two elements: 一个替代方案是使用itertools.groupby以检测字符的“脉冲串”,并在情况下,突发包含'o' S,我们islice(..)最多两个元素:

from itertools import groupby, islice 来自itertools import groupby,islice

[ x for k, g in groupby(bar) for x in (islice(g, 2) if k == 'o' else g) ]

again yielding: 再次屈服:

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

If you really want to do it with one comprehension list: 如果你真的想用一个理解列表来做:

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]

should work for your example. 应该适合你的榜样。

You can do: 你可以做:

>>> 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']

Using itertools.groupby if k is 0 we append all the items from that group, if k is 'o' we only append the first and last excluding the middle 'o' 's 使用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