2

Python 辞書のキーを値に変更したいのですが、元の辞書の値が一意ではありません。

ここに私が持っているものがあります:

year_person = {2000: ‘Linda’, 2001: ‘Ron’, 2002: ‘Bruce’, 2003: ‘Linda’, 2004: ‘Bruce’, 2005 ‘Gary’, 2006: ‘Linda’}

これは私がそれを変更したいものです:

person_year = {‘Linda’: 2000, ‘Ron’: 2001, ‘Bruce’: 2002, ‘Linda’, 2003: ‘Bruce’, 2004 ‘Gary’, 2005: ‘Linda’: 2006}

forループを使って変換しようとしたところ、1人につき1組しか一致しませんでした。

4

4 に答える 4

10

defaultdict を使用して行うこともできます。

year_person = {2000: 'Linda', 2001: 'Ron', 2002: 'Bruce', 2003: 'Linda', 2004: 'Bruce', 2005: 'Gary', 2006: 'Linda'}

from collections import defaultdict
d = defaultdict(list)
for k, v in year_person.items():
    d[v].append(k)

print dict(d)
>>> {'Bruce': [2002, 2004], 'Linda': [2000, 2003, 2006], 'Ron': [2001], 'Gary': [2005]}
于 2012-04-05T22:23:35.500 に答える
5

現在の回答に欠けている可能性のある他のオプションと情報をいくつか提示するだけです。

値が一意であり、したがってキーになる可能性があることが確実な場合、最も簡単な方法は辞書内包表記です。

year_person = {2000: 'Linda', 2001: 'Ron', 2002: 'Bruce', 2003: 'Linda', 2004: 'Bruce', 2005: 'Gary', 2006: 'Linda'}
person_year = {key: value for (value, key) in year_person.items()}

もちろん、あなたの場合はそうではないので、これは機能しません(最後に見つかった値のみを与えるため):

person_year = {'Bruce': 2004, 'Linda': 2006, 'Ron': 2001, 'Gary': 2005}

代わりに、辞書コンプ内でネストされたリストコンプを使用できます。

{key: [value for value, check_key in year_person.items() if check_key==key] for key in year_person.values()}

私たちに与えること:

{'Bruce': [2002, 2004], 'Linda': [2000, 2003, 2006], 'Ron': [2001], 'Gary': [2005]}

これは機能しますが、エントリごとに辞書全体をループする必要があるため、効率的ではありません。はるかに優れたソリューションは単一defaultdictのループのみを必要とする alan によって提供されるソリューションです。

于 2012-04-05T22:38:00.550 に答える
3

達成したくないことは、技術的に実現不可能です。ディクショナリのキーを複製することはできません。重複すると、キーを使用してディクショナリに一意のインデックスを付けることができないためです。

できることは、値が同じキーを持つすべてのアイテムのリストである (キー、値) ペアの辞書を作成することです。それを達成するには、次のようにすることができます

>>> person_year={}
>>> [person_year.setdefault(v,[]).append(k) for (k,v) in year_person.iteritems()]
[None, None, None, None, None, None, None]
>>> person_year
{'Bruce': [2002, 2004], 'Linda': [2000, 2003, 2006], 'Ron': [2001], 'Gary': [2005]}
>>> 

キーと値のペアのみに関心があり、辞書自体には関心がない場合は、次のようにタプルのリストとして保存できます。

>>> [(v,k) for k,v in year_person.iteritems()]
[('Linda', 2000), ('Ron', 2001), ('Bruce', 2002), ('Linda', 2003), ('Bruce', 2004), ('Gary', 2005), ('Linda', 2006)]
>>>
于 2012-04-05T22:18:10.153 に答える
2

ここではIMOdefaultdictは不要であり、リスト内包表記としてそれを行うと可読性が犠牲になります(ただし、一般的にはそうではありません)。プロファイリングでこれが本当にボトルネックであることが示されない限り、次のようにします。

def invert_to_lists(dct):
    inverted_dict = {}
    for key in dct:
        inverted_dict.setdefault(dct[key], []).append(key)
    return inverted_dict

defaultdictもう1つの複雑さです。setdefaultこの場合、一度入力するだけでよいため、使用しても問題ありません。をインポートしてインスタンス化するという難題を経るとdefaultdict、 を 1 回呼び出すだけでなく、複数のコードを入力することになりますsetdefault

于 2012-04-05T22:54:16.957 に答える