2010-01-03 58 views
15

有沒有辦法到一個列表映射到一個字典?我想要做的是給它一個函數,它將返回一個鍵的名稱,並且該值將是原始值。例如;地圖列表到字典

somefunction(lambda a: a[0], ["hello", "world"]) 
=> {"h":"hello", "w":"world"} 

(這不是我想要做一個具體的例子,我要像map()一個泛型函數可以做到這一點)

回答

22

我不認爲一個標準功能存在正是這麼做的,但它很容易構建一個使用內置的字典和理解:

def somefunction(keyFunction, values): 
    return dict((keyFunction(v), v) for v in values) 

print somefunction(lambda a: a[0], ["hello", "world"]) 

輸出:

{'h': 'hello', 'w': 'world'} 

但是爲這個功能提供一個好名字比實現它更困難。我將把它作爲讀者的練習。

+0

我在一個開放源代碼程序中,使用BSD樣式的許可證。我給你信貸,只是想確保你的好嗎? – 2010-01-03 19:17:12

+2

我對它很滿意,但是對於你能爲這麼小的貢獻提供明確的信用感到驚訝。 – 2010-01-03 20:28:35

+0

@MarkByers,尼斯,謝謝! – user1514631 2013-03-27 11:26:53

5

如果我正確理解你的問題,我相信你可以的mapzip組合實現這一點,和dict構造:

def dictMap(f, xs) : 
    return dict(zip(map(f, xs), xs) 

並有理智的實現:

def dictMap(f, xs) : 
    return dict((f(i), i) for i in xs) 
+0

該解決方案也適用於2.7.5。 – 2013-11-13 19:57:32

22

在Python 3中,你可以使用這個字典解析語法:

def foo(somelist): 
    return {x[0]:x for x in somelist} 
+3

這個語法在Python 2.7中也是可用的 – 2013-10-02 18:48:20

1

如果你想有一個通用的函數來做到這一點,那麼你要問幾乎是正確的問題。不過,您的示例並未指定在鍵函數產生重複項時會發生什麼情況。你保留最後一個嗎?第一個?你真的想列出所有以同一個字母開頭的單詞嗎?這些問題可能最好由功能用戶而不是設計人員來解答。

設定參數,對這些結果更復雜,但很一般,功能。這裏有一個,我已經用了好幾年:

def reduce_list(key, update_value, default_value, l): 
    """Reduce a list to a dict. 

    key :: list_item -> dict_key 
    update_value :: key * existing_value -> updated_value 
    default_value :: initial value passed to update_value 
    l :: The list 

    default_value comes before l. This is different from functools.reduce, 
    because functools.reduce's order is wrong. 
    """ 
    d = {} 
    for k in l: 
     j = key(k) 
     d[j] = update_value(k, d.get(j, default_value)) 
    return d 

然後你可以這樣寫你的函數:

reduce_list(lambda s:s, lambda s,old:s[0], '', ['hello', 'world']) 
# OR 
reduce_list(lambda s:s, lambda s,old: old or s[0], '', ['hello', 'world']) 

根據您是否要保留第一個或最後一個字開始,對例如,'h'。

這個功能是非常普遍的,雖然如此,大部分時間它的基礎,其他功能,如group_dicthistogram

def group_dict(l): 
    return reduce_list(lambda x:x, lambda x,old: [x] + old, [], l) 
def histogram(l): 
    return reduce_list(lambda x:x, lambda x,total: total + 1, 0, l) 
1
>>> dict((a[0], a) for a in "hello world".split()) 
{'h': 'hello', 'w': 'world'} 

如果你想使用的,而不是下標功能,使用operator.itemgetter:

>>> from operator import itemgetter 
>>> first = itemgetter(0) 
>>> dict((first(x), x) for x in "hello world".split()) 
{'h': 'hello', 'w': 'world'} 

或者作爲一個函數:

>>> dpair = lambda x : (first(x), x) 
>>> dict(dpair(x) for x in "hello world".split()) 
{'h': 'hello', 'w': 'world'} 

最後,如果你想每個字母多於一個字作爲一種可能性,使用集合。defaultdict

>>> from collections import defaultdict 
>>> words = defaultdict(set) 
>>> addword = lambda x : words[first(x)].add(x) 
>>> for word in "hello house home hum world wry wraught".split(): 
     addword(word) 


>>> print words['h'] 
set(['house', 'hello', 'hum', 'home']) 
0

從其他答案提示我使用地圖操作實現了這一點。我不確定這是否完全回答你的問題。

mylist = ["hello", "world"] 
def convert_to_dict(somelist): 
    return dict(map(lambda x: (x[0], x), somelist)) 

final_ans = convert_to_dict(mylist) 
print final_ans