有没有更好的等效于mapKeysWith的python?

时间:2018-11-28 19:16:49

标签: python python-3.x

Haskell具有此强大功能mapKeysWith。在映射的键上,它应用了一些变换,如果现在存在冲突,则将数据对象与给定的函数组合在一起。我在下面创建了示例代码,这很冗长。还有更Python化的方法吗?

def mapKeysWith(combineF,op,mp):
    ret = {}
    for it in mp:
        if op(it) in ret:
            ret[op(it)] = combineF(ret[op(it)],mp[it])
        else:
            ret[op(it)] = mp[it]
    return ret

z = {1:2,3:4,10:11}
mapKeysWith(lambda x,y: x+y,lambda x: math.floor(x/10),z)

1 个答案:

答案 0 :(得分:2)

以下是两种可能的选择:

import math
from functools import reduce
from collections import defaultdict


def map_keys_with(combine_f, op, mp):
    ret = {}
    for it in mp:

        if op(it) in ret:
            ret[op(it)] = combine_f(ret[op(it)], mp[it])
        else:
            ret[op(it)] = mp[it]
    return ret


def map_keys_with_setdefault(combine_f, op, mp):
    ret = {}
    for key, value in mp.items():
        ret.setdefault(op(key), []).append(value)

    return {key: reduce(combine_f, values) for key, values in ret.items()}


def map_keys_with_defaultdict(combine_f, op, mp):
    ret = defaultdict(list)
    for key, value in mp.items():
        ret[op(key)].append(value)
    return {key: reduce(combine_f, values) for key, values in ret.items()}


z = {1: 2, 3: 4, 10: 11}
print(map_keys_with(lambda x, y: x + y, lambda x: math.floor(x / 10), z))
print(map_keys_with_setdefault(lambda x, y: x + y, lambda x: math.floor(x / 10), z))
print(map_keys_with_defaultdict(lambda x, y: x + y, lambda x: math.floor(x / 10), z))

输出

{0: 6, 1: 11}
{0: 6, 1: 11}
{0: 6, 1: 11}