[英]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
: 上述步骤可以通过结合
sorted
和dictionary 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. 您的代码略有不同,但是想法几乎相同。
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.