web-dev-qa-db-ja.com

リストを辞書にマッピング

リストを辞書にマッピングする方法はありますか?私がやりたいことは、キーの名前を返す関数をそれに与え、値は元の値になります。例えば;

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

(これは私がやりたい具体的な例ではありません。これを行うことができるmap()のような汎用関数が必要です)

27

正確にそれを行う標準関数は存在しないと思いますが、組み込みのdictと内包を使用して簡単に作成できます。

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'}

ただし、この関数に適切な名前を付けることは、実装するよりも困難です。読者のための演習として残しておきます。

27
Mark Byers

Python 3では、この辞書内包表記構文を使用できます。

def foo(somelist):
    return {x[0]:x for x in somelist}
36
mkotechno

あなたの質問を正しく理解できれば、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)
5
sykora

一般的な関数でこれを行う場合は、ほぼ正しい質問をしていることになります。ただし、この例では、キー関数が重複を生成した場合の動作を指定していません。最後のものを残しますか?最初の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'])

最初または最後のWordを「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)

他の答えからヒントを得て、マップ操作を使用してこれを達成しました。これがあなたの質問に正確に答えるかどうかはわかりません。

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
1
Pulkit Bansal
>>> 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'}

最後に、可能性として文字ごとに複数のWordが必要な場合は、collections.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'])
1
Ryan Ginstrom