鉴于Python列表,我想删除连续的“重复项”。但是,重复值是列表项的属性(在此示例中,tuple
的第一个元素)。
输入:
[(1, 'a'), (2, 'b'), (2, 'b'), (2, 'c'), (3, 'd'), (2, 'e')]
所需的输出:
[(1, 'a'), (2, 'b'), (3, 'd'), (2, 'e')]
由于顺序很重要,因此无法使用set
或dict
。
不能使用列表推导[x for x in somelist if not determine(x)]
,因为检查取决于前任。
我想要的是这样的
mylist = [...]
for i in range(len(mylist)):
if mylist[i-1].attr == mylist[i].attr:
mylist.remove(i)
在Python中解决此问题的首选方法是什么?
答案 0 :(得分:16)
您可以使用itertools.groupby
(具有更多数据的演示):
from itertools import groupby
from operator import itemgetter
data = [(1, 'a'), (2, 'a'), (2, 'b'), (3, 'a'), (4, 'a'), (2, 'a'), (2, 'a'), (3, 'a'), (3, 'a')]
[next(group) for key, group in groupby(data, key=itemgetter(0))]
输出:
[(1, 'a'), (2, 'a'), (3, 'a'), (4, 'a'), (2, 'a'), (3, 'a')]
出于完整性考虑,一种基于其他答案的迭代方法:
result = []
for first, second in zip(data, data[1:]):
if first[0] != second[0]:
result.append(first)
result
输出:
[(1, 'a'), (2, 'b'), (3, 'a'), (4, 'a'), (2, 'a')]
请注意,这将保留最后一个(而不是第一个)重复。
答案 1 :(得分:12)
要删除连续的重复项,可以使用itertools.groupby
:
l = [(1, 'a'), (2, 'a'), (2, 'a'), (3, 'a'), (4, 'a')]
from itertools import groupby
[tuple(k) for k, _ in groupby(l)]
# [(1, 'a'), (2, 'a'), (3, 'a'), (4, 'a')]
答案 2 :(得分:7)
如果我没记错的话,您只需要查找最后一个值即可。
if (i === 0 && r.startAngle>180){
var centroidText = r.data.arc.centroid({
startAngle: r.startAngle,
endAngle: r.startAngle)
} else {
var centroidText = r.data.arc.centroid({
startAngle: r.startAngle*Math.pi,
endAngle: r.startAngle*Math.pi)
var lableObj = r.data.object; }
输出:
test = [(1, 'a'), (2, 'a'), (2, 'a'), (3, 'a'), (4, 'a'),(3, 'a'),(4,"a"),(4,"a")]
result = []
for i in test:
if result and i[0] == result[-1][0]: #edited since OP considers (1,"a") and (1,"b") as duplicate
#if result and i == result[-1]:
continue
else:
result.append(i)
print (result)
答案 3 :(得分:2)
如果您只想坚持列表理解,则可以使用以下内容:
>>> li = [(1, 'a'), (2, 'a'), (2, 'a'), (3, 'a'), (2, 'a')]
>>> [li[i] for i in range(len(li)) if not i or li[i] != li[i-1]]
[(1, 'a'), (2, 'a'), (3, 'a'), (2, 'a')]
请不要以not i
是写i == 0
的Python方式。
答案 4 :(得分:2)
您还可以使用enumerate
和列表理解:
>>> data = [(1, 'a'), (2, 'b'), (2, 'b'), (2, 'c'), (3, 'd'), (2, 'e')]
>>> [v for ix, v in enumerate(data) if not ix or v[0] != data[ix-1][0]]
[(1, 'a'), (2, 'b'), (3, 'd'), (2, 'e')]
答案 5 :(得分:1)
我会稍微修改Henry Yik的建议,使其变得更简单。不知道我是否想念什么。
inputList = [(1, 'a'), (2, 'a'), (2, 'a'), (3, 'a'), (2, 'a')]
outputList = []
lastItem = None
for item in inputList:
if not item == lastItem:
outputList.append(item)
lastItem = item
print(outputList)
答案 6 :(得分:1)
您可以轻松地zip
与列表本身一起使用。除第一个元素外,每个元素均以其前身压缩:
>>> L = [(1, 'a'), (2, 'b'), (2, 'b'), (2, 'c'), (3, 'd'), (2, 'e')]
>>> list(zip(L[1:], L))
[((2, 'b'), (1, 'a')), ((2, 'b'), (2, 'b')), ((2, 'c'), (2, 'b')), ((3, 'd'), (2, 'c')), ((2, 'e'), (3, 'd'))]
第一个元素始终是结果的一部分,然后根据条件过滤对并返回第一个元素:
>>> [L[0]]+[e for e, f in zip(L[1:], L) if e[0]!=f[0]]
[(1, 'a'), (2, 'b'), (3, 'd'), (2, 'e')]
答案 7 :(得分:1)
有点过分,但是您也可以使用“ reduce”:
from functools import reduce
data=[(1, 'a'), (2, 'b'), (2, 'b'), (2, 'c'), (3, 'd'), (2, 'e')]
reduce(lambda rslt,t: rslt if rslt[-1][0]==t[0] else rslt+[t], data, [data[0]])
[(1, 'a'), (2, 'b'), (3, 'd'), (2, 'e')]