簡體   English   中英

嘗試將嵌套的for循環的python轉換為list / dict理解

[英]Trying to convert python nested for loops to list/dict comprehension

我正在嘗試將以下代碼轉換為更具可讀性的代碼。

for x in list_of_dicts:
    for y in header:
        if y not in x.keys():
            x[y] = ''

它獲取字典列表,並為任何鍵添加默認值為=的key:value對
當前詞典中尚不存在的鍵。

我還是python的新手,因此將不勝感激。 我試過了:

return [x[y] = '' for x in list_of_dicts for y in header if y not in x.keys()]  

但我認為您不能使用“ =“

您不能使用dict理解功能將項目添加到dict; dict理解會創建一個與現有字典分開的新dict,並且如果您希望將新舊字典結合起來,則必須明確地這樣做,例如:

for x in list_of_dicts:
    x.update({y: '' for y in header if y not in x})

(請注意,在處理字典時,不需要y not in x.keys() ,因為您可以y not in x不添加y not in x 。)

如果您對擺脫該外部for一無所知,則要做的方法是創建新字典的新列表:

list_of_dicts2 = [dict(x, **{y: '' for y in header if y not in x}) for x in list_of_dicts]

這不是應該通過列表理解來解決的問題。 可以使用一些設置操作改進現有代碼:

for x in list_of_dicts:
    x.update((y, '') for y in header.viewkeys() - x)

這將達到相同的效果; header中缺少的鍵添加為空字符串。 對於Python 3,將viewkeys()替換為keys()

這利用字典視圖對象為我們提供了關於字典鍵的類似集合的視圖; 在Python 3中,此行為現在是默認設置。

如果我讀錯了您的問題,並且headers也不是字典,請對其進行顯式設置以獲得相同的好處:

header_set = set(header)
for x in list_of_dicts:
    x.update((y, '') for y in header_set.difference(x))

使用設置操作使代碼更具可讀性和效率,將任何循環確定設置差異推入優化的C例程中。

可以為此使用列表推導,但您不應:

[x.setdefault(y, '') for x in list_of_dicts for y in header]

您不應該這樣做的原因是,這會創建一個不需要的舊列表,但需要花費時間和內存。

您可以使用生成器理解,而無需創建大的舊列表:

import collections
def consume(iterator):
    collections.deque(iterator, maxlen = 0)

consume(x.setdefault(y, '') for x in list_of_dicts for y in header)

可以說,您也不應該這樣做,因為讀者並不真正希望理解會產生副作用,因此代碼可能會使他們感到恐懼和困惑。

沒錯,您不能理解x[y] = '' ,因為它是語句而不是表達式。 碰巧x.setdefault(y, '')您的要求,但是如果沒有這種方便的功能,那么您可以編寫一個。 並考慮一下,這樣做可以消除理解和原始循環:

def set_default(x, y):
    if y not in x:
        x[y] = ''

consume(itertools.starmap(set_default, itertools.product(list_of_dicts, header))

再說一次,關於使用發生器產生副作用的某種警告應該適用。

您可以通過多種方法來做到這一點。 通過更好地思考您要做什么來做主。

而你想做什么? 您可以這樣想:您想將默認值添加到某些字典中。 立即想到dict.setdefault()方法:

for d in list_of_dicts:
    for h in header:
        d.setdefault(h, '')

您可以以其他方式思考:我需要將一組默認值應用於所有dict。 現在先構造defaults dict,然后合並它就很自然了:

defaults = dict.fromkeys(header, '')
list_of_dicts = [dict(defaults, **d) for d in list_of_dicts]

請注意,我們在這里重建每個字典而不更新它。 這是使用理解力的正確方法。 在此添加的一件事是,將最后一行與構建list_of_dicts的代碼合並可能會很有意義(我不能肯定地說不知道)。

>>> d1={'a':1}
>>> d2={'b':2}
>>> d3={'c':3}
>>> listofdict=[d1, d2, d3]
>>> listofdict
[{'a': 1}, {'b': 2}, {'c': 3}]
>>> header = ['x', 'y']
>>> header
['x', 'y']
>>> [ x.update({k:''}) for x in listofdict for k in header if not x.get(k) ]
[None, None, None, None, None, None]
>>> listofdict
[{'a': 1, 'x': '', 'y': ''}, {'y': '', 'x': '', 'b': 2}, {'y': '', 'x': '', 'c': 3}]
>>> d1
{'a': 1, 'x': '', 'y': ''}
>>> d2
{'y': '', 'x': '', 'b': 2}
>>> d3
{'y': '', 'x': '', 'c': 3}
>>> 

暫無
暫無

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

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