簡體   English   中英

將元組列表映射到字典中

[英]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

在這里,三項元組被解壓到變量_keyval _是 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 編程中多次遇到過這個用於reducedict用例。 在我看來, 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.

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