Pythonic 方式在列表中查找重复映射,同时忽略某些键,然后组合重复映射以创建新列表

标签 python list dictionary duplicates ipython

我想编写一个接受以下输入的代码:

list (list of maps)
request_keys (list of strings)
operation (add,substract,multiply,concat)

代码将查看列表中除 request_keys 中给出的键之外的所有键具有相同值的映射。找到与搜索键中的值匹配的两个映射后,代码将对两个映射执行操作(加、多、减、连接)并将它们组合成一个映射。这个组合 map 基本上会取代其他两张 map 。

我编写了以下代码来执行此操作。代码只做了加法操作。可以扩展进行其他操作

In [83]: list
Out[83]: 
[{'a': 2, 'b': 3, 'c': 10},
 {'a': 2, 'b': 3, 'c': 3},
 {'a': 2, 'b': 4, 'c': 4},
 {'a': 2, 'b': 3, 'c': 2},
 {'a': 2, 'b': 3, 'c': 3}]

In [84]: %cpaste
Pasting code; enter '--' alone on the line to stop or use Ctrl-D.
:def func(list,request_keys):
:    new_list = []
:    found_indexes = []
:    for i in range(0,len(list)):
:        new_item = list[i]
:        if i in found_indexes:
:            continue
:        for j in range(0,len(list)):
:            if i != j and {k: v for k,v in list[i].iteritems() if k not in request_keys} == {k: v for k,v in list[j].iteritems() if k not in request_keys}:
:                found_indexes.append(j)
:                for request_key in request_keys:
:                    new_item[request_key] += list[j][request_key]
:        new_list.append(new_item)
:    return new_list
:--

In [85]: func(list,['c'])
Out[85]: [{'a': 2, 'b': 3, 'c': 18}, {'a': 2, 'b': 4, 'c': 4}]

In [86]: 

我想知道的是,是否有更快、内存效率更高、更干净、更Pythonic 的方法来做同样的事情?

谢谢

最佳答案

您手动生成所有组合,然后比较每个组合。这是相当浪费的。相反,我建议按匹配键将字典分组到另一个字典中,然后添加“相同”字典。另外,您忘记了 operator 参数。

import collections, operator, functools
def func(lst, request_keys, op=operator.add):
    matching_dicts = collections.defaultdict(list)
    for d in lst:
        key = tuple(sorted(((k, d[k]) for k in d if k not in request_keys)))
        matching_dicts[key].append(d)

    for group in matching_dicts.values():
        merged = dict(group[0])
        merged.update({key: functools.reduce(op, (g[key] for g in group)) 
                       for key in request_keys})
        yield merged

它的作用:首先,它创建一个字典,将两个字典必须相等的键值对映射到所有具有这些键值对的字典。然后,它迭代这些组中的字典,使用该组之一作为原型(prototype),并使用该组中所有字典的总和(或乘积,或其他内容,取决于运算符)更新它,以获取 required_keys.

请注意,这会返回一个生成器。如果您想要一个列表,只需像 list(func(...)) 那样调用它,或者将 merged 字典累积到列表中并返回该列表。

关于Pythonic 方式在列表中查找重复映射,同时忽略某些键,然后组合重复映射以创建新列表,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33142226/

相关文章:

python - 使用 lambda 访问列表中字典的值

python - 遍历列表,比较前面的元素和后面的元素

java - 无法将 <Object, Map<Object, Object>> Map 转换为更具体类型的 Map

iphone - 如何在 MKMapView 上绘制当前位置到所需位置之间的路线?

python - float 双重列表?

sorting - 如何按其值对 Map[string]int 进行排序?

python - cublas cublasZgemm() 比预期慢

python - RTSP 流和 OpenCV (Python)

python - 同情 : expression simplification

python - 如何在 Python 中将可变长度值追加到列表中