【问题标题】:Python comparison in a list of lists of tuples元组列表列表中的 Python 比较
【发布时间】:2016-12-30 00:41:24
【问题描述】:

我是 python 新手,我有一个关于元组列表比较的问题。 我有一个列表,其中包含元组中第二个元素的重复项,我只想打印该元组的第一次出现。 例如,对于这个列表:

[(1, 2), (5, 10), (6, 10), (24, 35), (30, 35)] 

我有这个功能:

def func(lst):
    list_first = []
    #Checks if 2 elements have the same second value.
    for i in range(len(lst)-1):
            if(lst[i][1] == lst[i+1][1]):
                    first =  (lst[i][0]),lst[i][1] 
                    list_first.append(first) #append only the first element
    print list_first

我的函数的输出是:

[(5, 10), (24, 35), (30, 35)]

但我的预期输出是:

[(5, 10), (24, 35)]

我该如何解决?

更新

我必须在列表列表中执行所有这些算法。 所以对于输入:

[[(0, 3), (1, 3), (2, 3), (3, 3), (4, 3)], [(5, 3), (6, 3), (7, 3), (8, 3), (9, 3)], [(10, 3), (11, 3), (12, 3), (13, 3), (14, 3)]]

我希望输出是:

[[(0, 3)], [(5, 3)], [(10, 3)]]

我已经尝试过改变我在这里得到的解决方案。 但我得到的只是:

[[(0, 3)], [(0, 3)], [(0, 3)]]

【问题讨论】:

  • 尝试用不同的例子在纸上运行程序,包括这个 [(1, 2), (5, 10), (6, 10), (24, 35), (30, 35) , (40, 35)]。这将向您展示算法的一些问题。

标签: python python-2.7 list tuples


【解决方案1】:

不假设输入排序的解决方案

您可以使用将元组中的第二个值用作键的字典。 如果 this 键第二次出现,请将已经看到的元组附加到您的结果中。如果您第三次或更多次看到元组,请不要再次追加。 如果找到两个以上的匹配项,则集合 added 包含已添加的第二个元组条目:

from __future__ import print_function # makes work in Python 2 and 3

def find_first(lst):
    seen = {}
    res = []
    added = set()
    for elem in lst:
        key = elem[1] 
        if key in seen and key not in added:
            res.append(seen[key])
            added.add(key)
        else:
            seen[key] = elem
    return res

使用 lis 进行测试。注意最后一个元素 (60, 10)10 第三次重复:

L = [(1, 2), (5, 10), (6, 10), (24, 35), (30, 35), (60, 10)] 
print(find_first(L))

输出:

[(5, 10), (24, 35)]

它确实使用排序并适用于此示例数据:

L = [(1, 2), (6, 10), (5, 10), (24, 35), (30, 35), (60, 10)] 
print(find_first(L))

输出:

[(6, 10), (24, 35)]

其他答案的解决方案不适用于此数据:

from itertools import groupby

L = [(1, 2), (6, 10), (5, 10), (24, 35), (30, 35), (60, 10)]  
final = []
for _, v in groupby(sorted(a) , lambda x : x[1]):
    b = list(v)
    if len(b) > 1:
        final.append(b[0])

print(final)

输出:

[(5, 10), (24, 35)]

【讨论】:

    【解决方案2】:

    使用来自itertools 模块的groupby 解决您的问题:

    编辑:就像@AKS 建议的那样,这是一个具有多种输入形式的函数。

    from itertools import groupby
    
    def comp_list(a = list()):
        final = []
        for _, v in groupby(sorted(a, key = lambda x : x[1]) , lambda x : x[1]):
            b = list(v)
            if len(b) > 1:
                final.append(b[0])
    
        return final
    
    a1 = [(1, 2), (5, 10), (6, 10), (24, 35), (30, 35)]
    a2 = [(1, 2), (5, 10), (6, 10), (24, 35), (30, 35), (40, 35)]
    a3 = [(5, 10), (24, 35), (30, 35), (20, 5), (15, 4), (21, 5), (13, 4)]
    a4 = [(1, 2),(6, 10), (5, 10), (24, 35), (30, 35)]
    
    print(comp_list(a1))
    print(comp_list(a2))
    print(comp_list(a3))
    print(comp_list(a4))
    

    输出:

    [(5, 10), (24, 35)]
    [(5, 10), (24, 35)]
    [(15, 4), (20, 5), (24, 35)]
    [(6, 10), (24, 35)]
    

    【讨论】:

    • 你真的不需要写3遍代码来演示示例。为什么不创建一个以a 作为输入并返回final 作为输出的函数呢?然后,您可以根据需要展示这些一个或多个示例。
    • 但是 a = [(1, 2),(6, 10), (5, 10), (24, 35), (30, 35)] 给了我 [(5, 10), (24, 35)]`
    • @MikeMüller 现在检查,我已经更新了我的解决方案。感谢您的评论。
    • 好多了。但是您仍然失去了订单:a5 = [(24, 35), (30, 35), (1, 2),(6, 10), (5, 10)]--> [(6, 10), (24, 35)]。订单保留将是:[(24, 35), (6, 10)]。但是从 OP 问题中不清楚这是否重要。 ;) 但是与O(n) 循环和一些O(1)dict 和设置查找相比,对大型列表进行排序可能会很昂贵。
    • This 为您提供 Python 时间复杂度的概览。一些theory 和一些get started
    【解决方案3】:

    这里有个小方法可以帮到你

    def removeDuplicateTuple(sampleList):
        uniqueList = []
        entryLog = {}
        processedEntries = []
        for x, y in sampleList:
            if entryLog.get(y)==None:
                entryLog[y] = (x,y)
            else:
                if(entryLog.get(y) not in processedEntries):
                    uniqueList.append(entryLog.get(y))
                    processedEntries.append(entryLog.get(y))
    
        return uniqueList
    

    测试: [(1, 2), (5, 10), (6, 10), (24, 35), (30, 35), (45, 2)]

    输出: [(5, 10), (24, 35), (1, 2)]

    【讨论】:

    • L= [(1, 2), (6, 10), (5, 10), (24, 35), (30, 35), (60, 10)] 的结果是 [(6, 10), (24, 35), (6, 10)]
    猜你喜欢
    • 2021-06-24
    • 1970-01-01
    • 1970-01-01
    • 2015-08-01
    • 2021-07-15
    • 1970-01-01
    • 1970-01-01
    • 2017-03-12
    • 1970-01-01
    相关资源
    最近更新 更多