2015-04-23 62 views
3

的列表的列表所以我有鍵列表:Python構建從密鑰列表中選擇一個詞典,和值

keys = ['id','name', 'date', 'size', 'actions'] 

我也有瓦萊斯的名單列表:

values= 
    [ 
     ['1','John','23-04-2015','0','action1'], 
     ['2','Jane','23-04-2015','1','action2'] 
    ] 

如何建立一個與這些值匹配的字典?

輸出應該是:

{ 
    'id':['1','2'], 
    'name':['John','Jane'], 
    'date':['23-04-2015','23-04-2015'], 
    'size':['0','1'], 
    'actions':['action1','action2'] 
} 

編輯: 我試圖用ZIP()和字典(),但是這隻會工作,如果值列表中有1名名單,即values = [['1','John','23-04-2015','0','action1']]

for list in values: 
    dic = dict(zip(keys,list)) 

我也想過用鍵初始化一個dic,然後建立自己的值列表,但我覺得必須有一個更簡單的方法來做到這一點。

dic = dict.fromkeys(keys) 

for list in values: 
    ids = list[0] 
    names = list[1] 
    dates = list[2] 
    sizes = list[3] 
    actions = list[4] 

,最後

dic['id'] = ids 
dic['name'] = names 
dic['date'] = dates 
dic['size'] = sizes 
dic['action'] = actions 

這似乎真的很傻,我想知道這樣做的更好的辦法會是什麼。

+0

你自己試過了嗎? – sshashank124

+0

我試圖使用函數zip(),但我似乎無法得到我想要的結果。 – Andrew

+1

請顯示您已經試過的代碼,以便我們可以幫助您 – sshashank124

回答

7
>>> keys = ['id','name', 'date', 'size', 'actions'] 
>>> values = [['1','John','23-04-2015','0','action1'], ['2','Jane','23-04-2015','1','action2']] 
>>> c = {x:list(y) for x,y in zip(keys, zip(*values))} 
>>> c 
{'id': ['1', '2'], 'size': ['0', '1'], 'actions': ['action1', 'action2'], 'date': ['23-04-2015', '23-04-2015'], 'name': ['John', 'Jane']} 
>>> print(*(': '.join([item, ', '.join(c.get(item))]) for item in sorted(c, key=lambda x: keys.index(x))), sep='\n') 
id: 1, 2 
name: John, Jane 
date: 23-04-2015, 23-04-2015 
size: 0, 1 
actions: action1, action2 

這使用幾個工具:

c與字典解析創建。理解是一種表達迭代的方式,如字典或列表。除了初始化一個空的迭代器,然後使用循環向它添加元素外,理解會移動這些語法結構。

result = [2*num for num in range(10) if num%2] 

相當於

result = [] 
for num in range(10): 
    if num%2: # shorthand for "if num%2 results in non-zero", or "if num is not divisible by 2" 
     result.append(2*num) 

,我們得到[2, 6, 10, 14, 18]

zip()創建一個元組生成器,其中每個元組的每個元素都是您傳遞給zip()的其中一個參數的對應元素。

>>> list(zip(['a','b'], ['c','d'])) 
[('a', 'c'), ('b', 'd')] 

zip()需要多個參數 - 如果你傳遞包含更小的子列表一個大名單,結果是不同的:

>>> list(zip([['a','b'], ['c','d']])) 
[(['a', 'b'],), (['c', 'd'],)] 

,通常不是我們想要的。但是,我們的values列表就是這樣一個列表:包含子列表的大列表。我們想要zip()這些子列表。這是使用*運算符的好時機。

*運算符表示一個「解包」迭代。

>>> print(*[1,2,3]) 
1 2 3 
>>> print(1, 2, 3) 
1 2 3 

它也可以用來在函數定義:

>>> def func(*args): 
... return args 
... 
>>> func('a', 'b', []) 
('a', 'b', []) 

所以,要創建字典,我們zip()值列表一起,然後zip(),隨着鑰匙。然後我們遍歷每一個元組並且創建一個字典,其中每個元組的第一個項目是關鍵字,第二個項目是值(作爲list而不是tuple)。爲了打印這個,我們可以製作一個大的循環結構,或者我們可以使發生器(比完整的數據結構(比如list)更快地進行組裝和處理)並遍歷它們,從而大量使用*來解壓縮東西。請記住,在Python 3中,print可以接受多個參數,如上所示。

我們將首先對字典進行排序,使用keys中的每個元素的位置作爲關鍵字。如果我們使用類似key=len的東西,它將每個元素髮送到len()函數,並使用返回的長度作爲關鍵字。我們使用lambda來定義一個內聯的未命名函數,該函數採用參數xreturnxlistkeys的索引。請注意,字典實際上沒有排序;我們只是設置它,所以我們可以按照排序順序遍歷它。

然後我們可以通過這個已排序的字典並將其元素組裝成可打印的字符串。在頂層,我們join()一個關鍵,其值由': '分隔。每個值的元素join()編號爲', '。請注意,如果元素不是字符串,我們將不得不將它們變成字符串以便join()工作。

>>> list(map(str, [1,2,3])) 
['1', '2', '3'] 
>>> print(*map(str, [1,2,3])) 
1 2 3 

的發電機,其yield s各自這些join()編線是隨後與*操作者解包,並且每個元件被髮送作爲參數傳遞給print(),指定'\n'(換行)的分離器,而不是默認' '(空間)。

使用循環代替理解和*是完全正確的,然後在您的邏輯功能後將它們重新排列到這樣的結構中,如果需要的話。這在大多數情況下並不是特別必要。理解有時會比等效循環執行得稍快,並且通過練習,您可能會喜歡理解的語法。不過,要學習操作符* - 這是一個用於定義函數的非常多用途的工具。也可以查看**(通常稱爲「雙星」或「kwargs」),它將字典解壓縮爲關鍵字參數,也可用於定義函數。

+0

請問您是否可以更詳細地解釋發生了什麼?特別是關於'*';我以前從未見過它。 – Andrew

+1

當然,我會在一個解釋中編輯。 – TigerhawkT3

相關問題