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)。有什么想法吗?
答案 0 :(得分:1)
我们可以检查上一个和下一个元素,并检查它们是否也是'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
可迭代对象。
以上内容在线性时间 O(n)中起作用,其中 n 是要处理的列表的长度。
一种替代方法是使用itertools.groupby
来检测字符的“突发”,并且如果突发中包含'o'
个字符,则我们islice(..)
最多包含两个元素:
从itertools导入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']
答案 1 :(得分:1)
如果您真的想用一个理解列表来做到这一点:
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]
应该适合您的示例。
答案 2 :(得分:1)
您可以这样做:
>>> 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']
答案 3 :(得分:0)
如果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']