如何根据python的前身删除列表项

时间:2019-04-17 08:57:13

标签: python list

鉴于Python列表,我想删除连续的“重复项”。但是,重复值是列表项的属性(在此示例中,tuple的第一个元素)。

输入:

[(1, 'a'), (2, 'b'), (2, 'b'), (2, 'c'), (3, 'd'), (2, 'e')]

所需的输出:

[(1, 'a'), (2, 'b'), (3, 'd'), (2, 'e')]

由于顺序很重要,因此无法使用setdict

不能使用列表推导[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中解决此问题的首选方法是什么?

8 个答案:

答案 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')]