簡體   English   中英

python dict.add_by_value(dict_2)?

[英]python dict.add_by_value(dict_2)?

問題:

>>> a = dict(a=1,b=2    )
>>> b = dict(    b=3,c=2)

>>> c = ???

c = {'a': 1, 'b': 5, 'c': 2}

所以,這個想法是兩個以最短的形式通過int / float值添加到字典。 這是我設計的一個解決方案,但我不喜歡它,因為它很長:

c = dict([(i,a.get(i,0) + b.get(i,0)) for i in set(a.keys()+b.keys())])

我認為必須有一個更短/更簡潔的解決方案(可能與reduce和操作員模塊有關嗎?itertools?)...任何想法?


更新:我真的希望找到更優雅的東西,比如“reduce(operator.add,key = itemgetter(0),a + b)”。 (顯然這不是真正的代碼,但你應該得到這個想法)。 但似乎這可能是一個夢想。


更新:仍然需要更簡潔的解決方案。 也許groupby可以幫忙嗎? 我用“reduce”/“groupby”提出的解決方案實際上並不簡潔:

from itertools import groupby
from operator import itemgetter,add

c = dict( [(i,reduce(add,map(itemgetter(1), v))) \
              for i,v in groupby(sorted(a.items()+b.items()), itemgetter(0))] )

最容易使用Counter

>>> from collections import Counter
>>> a = dict(a=1,b=2    )
>>> b = dict(    b=3,c=2)
>>> Counter(a)+Counter(b)
Counter({'b': 5, 'c': 2, 'a': 1})
>>> dict(Counter({'b': 5, 'c': 2, 'a': 1}))
{'a': 1, 'c': 2, 'b': 5}

解決不是“長度”而是表現,我會做以下事情:

>>> from collections import defaultdict
>>> def d_sum(a, b):
        d = defaultdict(int, a)
        for k, v in b.items():
            d[k] += v
        return dict(d)
>>> a = {'a': 1, 'b': 2}
>>> b = {'c': 2, 'b': 3}
>>> d_sum(a, b)
{'a': 1, 'c': 2, 'b': 5}

與原始代碼不同,它也兼容py3k。

在我的第一印象中,我會寫:

>>> c = a.copy()
>>> for k in b: c[k] = c.get(k, 0) + b[k]

如果你想要短代碼,你就在那里。

如果你想要干凈的代碼,繼承Ber的defaultdict並重載__add__

from collections import defaultdict

class summable(defaultdict):
    def __add__(self, rhs):
        new = summable()
        for i in (self.keys() + rhs.keys()):
            new[i] = self.get(i, 0) + rhs.get(i, 0)
        return new

a = summable(int, a=1, b=2)
b = summable(int, b=3, c=4)
c = a + b
print c

得到:

>>> 
defaultdict(None, {'a': 1, 'c': 4, 'b': 5})
>>> 

我認為一行代碼已經很短了:)

我可能會變成“半行”,你使用defaultdict並刪除一些不必要的列表並設置創建:

from collections import defaultdict

a = defaultdict(int, a=1, b=2)
b = defaultdict(int, b=3, c=4)

c = dict((k, a[k]+b[k]) for k in (a.keys() + b.keys()))
print c

我想到的第一件事是效率更高,(IMO)更優雅,但仍然打字太多。 實際上,它大約相當於kcwu的。

c = reduce(lambda(d, k): [d.update({k: d.get(k, 0) + b[k]}), d][1], b, a.copy())

dict.update不回歸self真是一種恥辱。 我想這不是Python的方式。 如果確實如此, [..., d][1]技巧將是不必要的。


Perl:“簡單易事,難事可能”

%a = (a => 1, b => 2);
%b = (b => 3, c => 2);

%c = (%a, map {$_ => $a{$_} + $b{$_}} keys %b);

哈斯克爾: “簡單的事情是艱難的,艱難的事情很容易” “硬事物很容易,不可能發生的事情”

import qualified Data.Map as M

a = M.fromList [('a', 1), ('b', 2)]
b = M.fromList [('b', 3), ('c', 2)]

c = M.unionWith (+) a b

評論@John Pirie的回答

這是不使用的實現(self.keys() + rhs.keys())

from collections import defaultdict

class sumdict(defaultdict):
    def __add__(self, rhs):
        d = self.copy() 
        d += rhs
        return d
    __radd__ = lambda self, lhs: self + lhs
    def __iadd__(self, rhs):
        for k, v in rhs.items():
            self[k] += v
        return self

a = sumdict(int, a=1, b=2)
b = dict(b=3, c=4)
c = b + a
a += b

assert a == c == {'a': 1, 'c': 4, 'b': 5} != b
def GenerateSum():
  for k in set(a).union(b):
    yield k, a.get(k, 0) + b.get(k, 0)

e = dict(GenerateSum())
print e

或者,用一個班輪:

 print dict((k, a.get(k,0) + b.get(k,0)) for k in set(a).union(b))

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM