如何使用元组项筛选元组列表?

时间:2018-06-19 03:03:19

标签: python

我有这个清单 -

d = [('A', 'B', 1), ('C', 'D', 1), 
     ('B', 'D', 2), ('A', 'B', 3), 
     ('A', 'D', 3), ('B', 'C', 4), 
     ('A', 'C', 5), ('B', 'C', 8)]

这里元组中的前两项是节点,第三项是权重。我想删除具有相同的第一和第二节点(两个元组之间相同的第一和第二节点)但重量更高的元组。

最终名单:

d = [('A', 'B', 1), ('C', 'D', 1), 
     ('B', 'D', 2), ('A', 'D', 3), 
     ('B', 'C', 4), ('A', 'C', 5)]

我尝试过类似的东西,但看起来不是一个非常干净的解决方案。

edge_dict = {}

for x in d:
    key = '%s%s' % (x[0], x[1])
    if not edge_dict.get(key):
        edge_dict[key] = x[2]
    else:
        if edge_dict[key] > x[2]:
            edge_dict[key] = x[2]       

final_list = []
for k, v in edge_dict.items():
    t = list(k)
    t.append(v)
    final_list.append(tuple(t))


final_list.sort(key=lambda x: x[2])
print final_list    

4 个答案:

答案 0 :(得分:2)

另一种方法可能是首先在每个元组的前两个元素上排序元组列表,然后按顺序排序最后一个元素:

sorted_res = sorted(d, key = lambda x:((x[0], x[1]), x[2]),reverse=True)
print(sorted_res)

结果:

[('C', 'D', 1),
 ('B', 'D', 2),
 ('B', 'C', 8),
 ('B', 'C', 4),
 ('A', 'D', 3),
 ('A', 'C', 5),
 ('A', 'B', 3),
 ('A', 'B', 1)]

现在使用前两个元素和值的键创建dictionary将是最新的一个小的:

my_dict = {(i[0], i[1]):i for i in sorted_res}
print(my_dict)

结果:

{('A', 'B'): ('A', 'B', 1),
 ('A', 'C'): ('A', 'C', 5),
 ('A', 'D'): ('A', 'D', 3),
 ('B', 'C'): ('B', 'C', 4),
 ('B', 'D'): ('B', 'D', 2),
 ('C', 'D'): ('C', 'D', 1)}

最终结果是字典的值:

list(my_dict.values())

结果:

[('A', 'C', 5),
 ('A', 'B', 1),
 ('A', 'D', 3),
 ('B', 'D', 2),
 ('C', 'D', 1),
 ('B', 'C', 4)]

上述步骤可以通过合并sorteddictionary comprehension

来完成
result = list({(i[0], i[1]):i 
             for i in sorted(d, key = lambda x:((x[0], x[1]), x[2]),reverse=True)}.values())

答案 1 :(得分:2)

稍微重构一下。

edge_dict = {}

for t in d:
    key = t[:2]
    value = t[-1]
    if key in edge_dict:
        edge_dict[key] = min(value, edge_dict[key]) 
    else:
        edge_dict[key] = value

final_list = [(q,r,t) for (q,r),t in edge_dict.items()]
final_list.sort(key=lambda x: x[2])

答案 2 :(得分:1)

您可以使用itertools.groupby,并在每个分组中选择最小值:

import itertools
d = [('A', 'B', 1), ('C', 'D', 1), 
 ('B', 'D', 2), ('A', 'B', 3), 
 ('A', 'D', 3), ('B', 'C', 4), 
 ('A', 'C', 5), ('B', 'C', 8)]
new_d = [min(list(b), key=lambda x:x[-1]) for _, b in itertools.groupby(sorted(d, key=lambda x:x[:-1]), key=lambda x:x[:-1])]

输出:

[('A', 'B', 1), ('A', 'C', 5), ('A', 'D', 3), ('B', 'C', 4), ('B', 'D', 2), ('C', 'D', 1)]

答案 3 :(得分:1)

您的代码略有不同,但想法几乎相同。

  1. 检查先前是否找到了Node对,如果没有找到,则将其存储而不进行任何比较。
  2. 如果先前找到的节点对然后比较这些值并存储最小值
  3. 使用排序形式的节点对作为字典sudo resize2fs /dev/nvme0n1来处理(' B' A' A')为(' A',&# 39; B&#39)
  4. 另请阅读评论以获得更好的说明:

    key

    输出:

    check_dict={} #This will store the minimum valued nodes
    
    for i in d:
        if check_dict.get((i[0],i[1])) ==None: #if the node is absent then add it to the check_dict
            check_dict[tuple(sorted((i[0],i[1])))] = i[2]
        else: #if the node is present then compare with the previous value and store the minimum one
            check_dict[tuple(sorted((i[0],i[1])))] = min(check_dict[(i[0],i[1])],i[2]) #used sorted to treat ('A','B') as same as ('B',A')
    expected_list = [tuple(key+(value,)) for key,value in check_dict.items()] #create your list of tuples
    print(expected_list)