【问题标题】:Merging ranked lists of tuples based on common id基于公共 id 合并元组的排序列表
【发布时间】:2021-09-15 03:38:49
【问题描述】:

我有以下排序的元组列表:

list1 = [(0.2, 'a'), (0.4, 'b'), (0.5,'d')]
list2 = [(0.1, 'a'), (0.3, 'c'), (0.7, 'x')]
list3 = [(0.5, 'c'), (0.6, 'a'), (0.5, 'b')]

我想根据常用字母创建一个整体排名列表,如下所示:

  1. 如果该字母在所有三个列表中都通用,则添加三个单独的值
  2. 如果该字母仅在两个列表之间通用,则添加两个单独的值和一个 1
  3. 如果元素只在一个列表中,则将其值加 2

预期结果:

[(0.9, 'a'), (1.8, 'c'), (1.9, 'b'), (2.5, 'd'), (2.7, 'x')]

什么是有效的:

如果该项目在所有三个列表中都很常见,我可以获得预期的结果,但如果是其他情况,我无法获得正确的结果。

代码sn-p

list1 = [(0.2, 'a'), (0.4, 'b'), (0.5, 'd')]
list2 = [(0.1, 'a'), (0.3, 'c'), (0.7, 'x')]
list3 = [(0.5, 'c'), (0.6, 'a'), (0.5, 'b')]
priority_result = [] # when element is common in all 3 lists
twos_array = [] #when element is common in only two lists

result = [(s1, l1 + l1) for (l1, s1), (l1, s2) in zip(list1, list2)]
print(result)
for (score, resultID) in list1:
    for (score1, resultID1) in list2:
        for (score2, resultID2) in list3:
            if(resultID == resultID1 or resultID == resultID2):                    
                result = [(score + score1 + score2, resultID)]
                priority_result.extend(result)
            elif(resultID == resultID1 and resultID != resultID2):
                result = [(score + score1 + 1, resultID)]
                twos_array.extend(result)

我该如何做才能产生预期的结果?

【问题讨论】:

    标签: python list tuples


    【解决方案1】:

    您可以交换元组的顺序来创建映射:

    d1 = dict(x[::-1] for x in list1)
    d2 = dict(x[::-1] for x in list2)
    d3 = dict(x[::-1] for x in list3)
    

    现在您可以合并键,因为dict.keys 返回一个类似set 的对象:

    keys = d1.keys() | d2.keys() | d3.keys()
    

    剩下的可以用dict.get:

    result = {k: d1.get(k, 1) + d2.get(k, 1) + d3.get(k, 1) for k in keys}
    

    将其转换为排序列表很简单:

    sorted(x[::-1] for x in result.items())
    

    假设您的列表现在位于元列表中:

    lists = [list1, list2, list3]
    keys = set().union(*lists)
    dicts = [dict(x[::-1] for x in l) for l in lists]
    result = {k: sum(d.get(k, 1) for d in dicts) for k in keys}
    result = sorted(x[::-1] for x in result.items())
    

    这是一个稍微简单的解决方案:

    mapping = dict.fromkeys(set().union(*lists), len(lists))
    for v, k in itertools.chain.from_iterable(lists):
        mapping[k] += v - 1
    result = sorted(x[::-1] for x in result.items())
    

    您可以使用collections.Counter 为您完成大部分数学运算:

    c = Counter()
    for lst in lists:
        c.update({k: v - 1 for v, k in lst})
    result = [(v + len(lists), k) for k, v in c.items()]
    

    与普通collections.defaultdict 相同的是:

    d = defaultdict(int)
    for v, k in itertools.chain.from_iterable(lists):
        d[k] += v - 1
    result = [(v + len(lists), k) for k, v in d.items()]
    

    【讨论】:

    • @Mark d1.get(k, 1) + d2.get(k, 1) + d3.get(k, 1) 完全按照 op 的要求,不是吗?您为每个缺少密钥的 dict 设置 1
    • 对不起,你是对的。不确定 DV。
    • @Kumbudzi。我添加了一个更简单的答案
    【解决方案2】:
    list1 = [(0.2, 'a'), (0.4, 'b'), (0.5, 'd')]
    list2 = [(0.1, 'a'), (0.3, 'c'), (0.7, 'x')]
    list3 = [(0.5, 'c'), (0.6, 'a'), (0.5, 'b')]
    
    d = {}
    for t in list1 + list2 + list3:
        d.setdefault(t[1], []).append(t[0])
    lst = [(sum(v, 3 - len(v)), k) for k, v in d.items()]
    print(lst)  # [(0.9, 'a'), (1.9, 'b'), (2.5, 'd'), (1.8, 'c'), (2.7, 'x')]
    

    【讨论】:

    • 感谢您的想法。如果您在所有键的联合上使用dict.fromkeys 进行初始化,则可以直接添加而不使用setdefault
    • @MadPhysicist dict.fromkeys 将使用[] 的一个实例初始化所有列表,因此将为所有键添加所有添加的值:d = dict.fromkeys([t[1] for t in list1 + list2 + list3], [])。还是我误会了?
    • 看看我的回答。你用 3 初始化它
    【解决方案3】:

    您可以尝试将itertools.groupbyoperator.itemgetter 一起使用:

    from itertools import groupby
    from operator import itemgetter
    x = list1 + list2 + list3
    y = [l[1] for l in x]
    print(sorted([((3 - y.count(key)) + sum(next(zip(*l))), key) for key, l in groupby(sorted(x, key=ig(1)), key=ig(1))], key=ig(0)))
    

    [(0.9, 'a'), (1.8, 'c'), (1.9, 'b'), (2.5, 'd'), (2.7, 'x')]
    

    此代码连接列表并为仅键创建另一个列表,并按键分组,总结值。它还根据出现的次数增加了预期的值增加。

    最后它按总和和修改后的值排序。

    【讨论】:

    • [*zip(*x)] -> list(zip(*x)),或者只是[e[1] for e in x]
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-06-11
    • 2020-01-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多