web-dev-qa-db-ja.com

値ごとに複数のキー

Python辞書の値ごとに複数のキーを割り当てることは可能ですか。1つの可能な解決策は、各キーに値を割り当てることです。

dict = {'k1':'v1', 'k2':'v1', 'k3':'v1', 'k4':'v2'}

ただし、データファイルが2 GBを超えるため、これはメモリ効率がよくありません。それ以外の場合は、辞書キーの辞書を作成できます。

key_dic = {'k1':'k1', 'k2':'k1', 'k3':'k1', 'k4':'k4'}
dict = {'k1':'v1', 'k4':'v2'}
main_key = key_dict['k2']
value = dict[main_key]

また、辞書/ファイル全体を2回調べる必要があるため、これも非常に時間と労力がかかります。他の簡単で組み込みのPythonソリューション?

注:私の辞書の値は単純な文字列(質問 'v1'、 'v2'のような)ではなく、複雑なオブジェクト(異なる他の辞書/リストなどを含み、それらをピクルすることはできません)

注:質問は 同じ辞書値にキーとインデックスの両方を使用するにはどうすればよいですか? に似ていますが、順序付き/インデックス付き辞書を探していません。この質問で言及された2つ以外の他の効率的なソリューション(ある場合)。

35
d.putto

値はどのタイプですか?

_dict = {'k1':MyClass(1), 'k2':MyClass(1)}
_

重複する値オブジェクトを提供しますが、

_v1 = MyClass(1)
dict = {'k1':v1, 'k2':v1}
_

両方のキーが同じ実際のオブジェクトを参照することになります。

元の質問では、値は文字列です。同じ文字列を2回宣言していても、その場合は同じオブジェクトにインターンされると思います


NB。重複しているかどうかわからない場合は、次のように確認できます。

_if dict['k1'] is dict['k2']:
    print("good: k1 and k2 refer to the same instance")
else:
    print("bad: k1 and k2 refer to different instances")
_

is J.F. Sebastianに感謝し、id()を置き換えます)

37
Useless

これをチェックしてください-それはまさにあなたが求めているものの実装です:multi_key_dict(ionary)

https://pypi.python.org/pypi/multi_key_dict (ソースは https://github.com/formiaczek/python_data_structures/tree/master/multi_key_dict

(Unixプラットフォームでは、パッケージとして提供される可能性があり、次のような方法でインストールを試みることができます。

Sudo apt-get install python-multi-key-dict

debianの場合、またはディストリビューションに相当するもの)

キーには異なるタイプを使用できますが、同じタイプのキーも使用できます。また、選択したキータイプを使用してアイテムを反復処理することもできます。

m = multi_key_dict()
m['aa', 12] = 12
m['bb', 1] = 'cc and 1'
m['cc', 13] = 'something else'

print m['aa']   # will print '12'
print m[12]     # will also print '12'

# but also:
for key, value in m.iteritems(int):
    print key, ':', value
# will print:1
# 1 : cc and 1
# 12 : 12
# 13 : something else

# and iterating by string keys:
for key, value in m.iteritems(str):
    print key, ':', value
# will print:
# aa : 12
# cc : something else
# bb : cc and 1

m[12] = 20 # now update the value
print m[12]   # will print '20' (updated value)
print m['aa']   # will also print '20' (it maps to the same element)

キーの数に制限はないので、次のようなコード:

m['a', 3, 5, 'bb', 33] = 'something' 

は有効であり、どちらかのキーを使用して、そのように作成された値を参照(読み取り/書き込みまたは削除)できます。

編集:バージョン2.0からは、python3でも動作するはずです。

10
formiaczek

辞書でタプルを使用することについて誰も言及していないことに驚いています。これはうまく機能します:

my_dictionary = {}
my_dictionary[('k1', 'k2', 'k3')] = 'v1'
my_dictionary[('k4')] = 'v2'
2
Justin Bozonier

python 2.7/3を使用すると、タプルと値のペアを辞書内包表記と組み合わせることができます。

keys_values = ( (('k1','k2'), 0), (('k3','k4','k5'), 1) )

d = { key : value for keys, value in keys_values for key in keys }

同様に辞書を更新することもできます。

keys_values = ( (('k1',), int), (('k3','k4','k6'), int) )

d.update({ key : value for keys, value in keys_values for key in keys })

これは本当にあなたの質問の核心になるとは思いませんが、タイトルに照らして、これはここに属すると思います。

2
blahreport

これを行う最も簡単な方法は、dict.fromkeys()メソッドを使用して辞書を作成することです。入力として一連のキーと値を受け取り、各キーに値を割り当てます。
あなたのコードは次のようになります。

dict = dict.fromkeys(['k1', 'k2', 'k3'], 'v1')
dict.update(dict.fromkeys(['k4'], 'v2'))

出力は次のとおりです。

print(dict)
{'k1': 'v1', 'k2': 'v1', 'k3': 'v1', 'k4': 'v2'}
2
bloodrootfc

解析済みのデータから既に作成されたオブジェクトの補助辞書を作成できます。キーは解析されたデータになり、値は構築されたオブジェクトになります。たとえば、文字列値を特定のオブジェクトに変換する必要があります。この方法で、新しいオブジェクトをいつ構築するかを制御できます。

_existing = {}   # auxiliary dictionary for making the duplicates shared
result = {}
for k, v in parsed_data_generator():
    obj = existing.setdefault(v, MyClass(v))  # could be made more efficient
    result[k] = obj
_

その後、すべてのresult辞書重複値オブジェクトは、MyClassクラスの単一オブジェクトによって表されます。結果を作成したら、existing補助辞書を削除できます。

ここで、dict.setdefault()はエレガントで簡潔な場合があります。ただし、よりおしゃべりなソリューションの方が効率的でないかどうかを後でテストする必要があります。以下を参照してください。理由は、MyClass(v)は常に作成され(上記の例では)、重複が存在する場合は破棄されるためです。

_existing = {}   # auxiliary dictionary for making the duplicates shared
result = {}
for k, v in parsed_data_generator():
    if v in existing:
        obj = existing[v]
    else:
        obj = MyClass(v)
        existing[v] = obj

    result[k] = obj
_

この手法は、vが特別なものに変換されない場合にも使用できます。たとえば、vが文字列の場合、補助辞書のキーと値は同じ値になります。ただし、ディクショナリの存在により、オブジェクトが共有されることが保証されます(Pythonによって常に保証されるとは限りません)。

1
pepr

私の場合、値はスカラーですが、pandas MultiIndex を使用して同様の機能を実現できました。

>>> import numpy
>>> import pandas
>>> keys = [numpy.array(['a', 'b', 'c']), numpy.array([1, 2, 3])]
>>> df = pandas.DataFrame(['val1', 'val2', 'val3'], index=keys)
>>> df.index.names = ['str', 'int']
>>> df.xs('b', axis=0, level='str')
        0
int      
2    val2

>>> df.xs(3, axis=0, level='int')
        0
str      
c    val3
1
robodasha