[英]Map list of tuples into a dictionary
我有一個從數據庫表中提取的元組列表,它看起來像 ( key , foreignkey , value )。 鍵和外鍵之間存在多對一關系,我想將其轉換為由外鍵索引的字典,其中包含具有該外鍵的所有值的總和,即 {外鍵, sumof ( value ) }。 我寫了一些相當冗長的東西:
myDict = {}
for item in myTupleList:
if item[1] in myDict:
myDict [ item[1] ] += item[2]
else:
myDict [ item[1] ] = item[2]
但是在看到這個問題的答案或這兩個答案之后,必須有一種更簡潔的方式來表達我想做的事情。 如果這是重復,我錯過了,如果你能提供鏈接,我會刪除這個問題。
假設您的所有值都是int
,您可以使用defaultdict
使這更容易:
from collections import defaultdict
myDict = defaultdict(int)
for item in myTupleList:
myDict[item[1]] += item[2]
defaultdict
就像一個字典,除非您嘗試獲取一個不存在的鍵,它會填充可調用對象返回的值 - 在這種情況下, int
,在不帶參數調用時返回 0 。
更新:感謝@gnibbler提醒我,但是元組可以在 for 循環中解包:
from collections import defaultdict
myDict = defaultdict(int)
for _, key, val in myTupleList:
myDict[key] += val
在這里,三項元組被解壓到變量_
、 key
和val
。 _
是 Python 中常見的占位符名稱,用於表示該值並不重要。 使用這個,我們可以避免多毛的item[1]
和item[2]
索引。 如果myTupleList
中的元組大小不同,我們就不能依賴這一點,但我敢打賭它們是。
(我們也避免了有人在查看代碼並認為它已損壞的情況,因為作者認為數組是 1 索引的,這是我第一次閱讀代碼時的想法。直到我讀到問題,我才緩解了這一點. 然而,在上面的循環中,很明顯myTupleList
是一個由三個元素組成的元組,我們只是不需要第一個。)
from collections import defaultdict
myDict = defaultdict(int)
for _, key, value in myTupleList:
myDict[key] += value
這是我的(臉頰上的舌頭)回答:
myDict = reduce(lambda d, t: (d.__setitem__(t[1], d.get(t[1], 0) + t[2]), d)[1], myTupleList, {})
它既丑陋又糟糕,但這是它的工作原理。
reduce 的第一個參數(因為它不清楚)是lambda d, t: (d.__setitem__(t[1], d.get(t[1], 0) + t[2]), d)[1]
. 我稍后會討論這個,但現在,我將它稱為joe
(無意冒犯任何名為 Joe 的人)。 reduce 函數基本上是這樣工作的:
joe(joe(joe({}, myTupleList[0]), myTupleList[1]), myTupleList[2])
這是一個三元素列表。 如您所見,它基本上使用其第一個參數將每個結果累積到最終答案中。 在這種情況下,最終答案是您想要的字典。
現在是joe
本身。 這是作為def
joe
:
def joe(myDict, tupleItem):
myDict[tupleItem[1]] = myDict.get(tupleItem[1], 0) + tupleItem[2]
return myDict
不幸的是,Python lambda
不允許出現任何形式的=
或return
,因此必須解決這個問題。 我通過直接調用dict
的__setitem__
函數來解決缺少=
的問題。 我通過使用__setitem__
和字典的返回值創建一個元組,然后返回包含字典的元組元素來解決缺少返回的問題。 我會慢慢改變joe
這樣你就可以看到我是如何做到這一點的。
首先,刪除=
:
def joe(myDict, tupleItem):
# Using __setitem__ to avoid using '='
myDict.__setitem__(tupleItem[1], myDict.get(tupleItem[1], 0) + tupleItem[2])
return myDict
接下來,使整個表達式計算為我們要返回的值:
def joe(myDict, tupleItem):
return (myDict.__setitem__(tupleItem[1], myDict.get(tupleItem[1], 0) + tupleItem[2]),
myDict)[1]
我在 Python 編程中多次遇到過這個用於reduce
和dict
用例。 在我看來, dict
可以使用成員函數reduceto(keyfunc, reduce_func, iterable, default_val=None)
。 keyfunc
將從可迭代對象中獲取當前值並返回鍵。 reduce_func
將獲取字典中的現有值和迭代中的值,並返回字典的新值。 如果字典缺少鍵,則default_val
將是傳遞給reduce_func
的內容。 返回值應該是字典本身,因此您可以執行以下操作:
myDict = dict().reduceto(lambda t: t[1], lambda o, t: o + t, myTupleList, 0)
也許不完全可讀,但它應該可以工作:
fks = dict([ (v[1], True) for v in myTupleList ]).keys()
myDict = dict([ (fk, sum([ v[2] for v in myTupleList if v[1] == fk ])) for fk in fks ])
第一行查找所有唯一的外鍵。 第二行通過首先構造一個 (fk, sum(all values for this fk))-pairs 列表並將其轉換為字典來構建您的字典。
看看SQLAlchemy ,看看它是否完成了你需要的所有映射,也許更多
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.