简体   繁体   English

如何用元组项过滤元组列表?

[英]How to filter list of tuples with an item of a tuple?

I have this list - 我有这个清单-

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)]

Here first two items in the tuple are nodes, and the third item is the weight. 这里,元组中的前两项是节点,而第三项是权重。 I want to remove the tuple with same 1st and 2nd nodes (same 1st and 2nd node between two tuples) but higher weight. 我想删除具有相同的第一和第二个节点(两个元组之间的第一和第二个节点相同)的元组,但是权重更高。

Final List: 最终名单:

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

I have tried something like this, but looks like not a very clean solution. 我已经尝试过类似的方法,但是看起来不是一个很干净的解决方案。

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    

One other way may be to first sorting the list of tuples on first two elements of each tuple and descending order for last element: 另一种方法可能是首先对每个元组的前两个元素上的元组列表进行排序,最后一个元素的降序排列:

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

Result: 结果:

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

Now creating dictionary with key of first two element and value will be the latest one which is small: 现在使用前两个元素和值的键创建dictionary将是最新的dictionary ,该dictionary很小:

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

Result: 结果:

{('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)}

Final result is values of dictionary: 最终结果是字典的值:

list(my_dict.values())

Result: 结果:

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

Above steps can be done by combining sorted and dictionary comprehension : 上述步骤可以通过结合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())

Just a little refactoring. 只是一点重构。

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])

You can use itertools.groupby , and select the minimum value in each grouping: 您可以使用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])]

Output: 输出:

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

Slightly different of your code but idea is almost same. 您的代码略有不同,但是想法几乎相同。

  1. Check whether the Node pair is previously found, if not found then store it without any comparison. 检查是否先前找到了节点对,如果找不到,则将其存储而不进行任何比较。
  2. If the node pair previously found then compare the values and store the minimum value 如果先前找到了节点对,则比较这些值并存储最小值
  3. Use sorted form of node pair as dictionary key to treat ('B','A') as ('A','B'). 使用节点对的排序形式作为字典key ,将('B','A')视为('A','B')。

Also read the comments for better clarification: 另请阅读评论以进行更好的说明:

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)

Output : 输出:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM