Python3でのインデックスによるdict_keys要素へのアクセス


131

インデックスでdict_keyの要素にアクセスしようとしています:

test = {'foo': 'bar', 'hello': 'world'}
keys = test.keys()  # dict_keys object

keys.index(0)
AttributeError: 'dict_keys' object has no attribute 'index'

欲しいですfoo

と同じ:

keys[0]
TypeError: 'dict_keys' object does not support indexing

これどうやってするの?


9
py3.x dict.keys()では、リストではなくビューオブジェクトのようなセットを返します(したがって、インデックス付けはできません)。使用keys = list(test)
Ashwini Chaudhary 2013

list(something_dict)を実行すると、タプルの順序はランダムです:例:list({'foo': 'bar'、 'hello': 'world'})は次を返すことができます:list(foo、hello)またはlist(hello、 foo)、なぜこれがランダムなのですか?
fj123x 2013

7
辞書には順序がありません。(collections.OrderedDictキーを注文したい場合に使用します)
Ashwini Chaudhary 2013

スレッドの安全性に関する興味深い議論が、ここでこの問題を解決するために様々なアプローチをreagrding: blog.labix.org/2008/06/27/...
ポール・

回答:


161

list()代わりに辞書を呼び出してください:

keys = list(test)

Python 3では、dict.keys()メソッドはセットとして機能するディクショナリビューオブジェクトを返します。ディクショナリを直接反復するとキーも生成されるため、ディクショナリをリストに変換すると、すべてのキーのリストが生成されます。

>>> test = {'foo': 'bar', 'hello': 'world'}
>>> list(test)
['foo', 'hello']
>>> list(test)[0]
'foo'

3
Python 3のlist(dict.keys())に注意してください。Labixブログでは、ソリューションを提供せずに問題が何であるかを明確に説明しています。これは素晴らしい!
Brandon Bradley

@BrandonBradley:一般的に言えば、Pythonは非常に動的であるため、特定のアクションがアトミックであることを信頼することはとにかく悪い考えです。dictたとえば、.keys()Pythonコードで処理される場合に、コードにサブクラスを簡単に渡すことができます(たとえば、スレッドの切り替えを行うことができます)。
Martijn Pieters

@BrandonBradley:リンクをありがとう。そのブログのコメントの1つからの解決策のみが、Python3で私のために機能します。sorted(dict.keys())。Python2では、dict.keys()はキー値のリストを返します。
グッドウィル

2
@GoodWill:sorted(dict)まったく同じことを行います。ソートされた順序でキーのリストを生成します。list(dict)辞書順にリストが表示されます。
Martijn Pieters

1
または使用可能keys = [*test]
Alex78191

59

完全な答えではありませんが、役に立つヒントかもしれません。それが本当に最初に欲しいアイテムである場合*、

next(iter(q))

よりもはるかに速いです

list(q)[0]

大規模な辞書の場合、すべてをメモリに保存する必要はありません。

10.000.000アイテムの場合、約40.000倍高速であることがわかりました。

* dictがPython 3.6より前の単なる疑似ランダムアイテムの場合の最初のアイテム(その後は、標準実装で順序付けされていますが、それに依存することはお勧めしません)。


5
これは常に、すべてがPy3のイテレータになるという私の最大の問題の1つでした。それは間違いなくより効率的ですが、非常に多くのユースケースが理由もなく「クリーン」でなく複雑になります。たとえば、必ずしもパフォーマンスを低下させることなく、イテレータのインデックス作成をサポートできないのはなぜですか?
Ehsan Kia


0
test = {'foo': 'bar', 'hello': 'world'}
ls = []
for key in test.keys():
    ls.append(key)
print(ls[0])

静的に定義されたリストにキーを追加し、同じようにインデックスを付ける従来の方法


2
間違いではありませんが、なぜls = list(test.keys())でしょうか?私はそれがもっと簡単だと思う。
Valentino

はい、これはより効率的です。これは読みやすさを示すためだけに書きました。
pranav dua

0

多くの場合、これはXY問題である可能性があります。辞書キーを位置で索引付けするのはなぜですか?あなたは本当にする必要がありますか?最近まで、辞書はPythonでも順序付けされていなかったため、最初の要素へのアクセスは任意でした。

Python 2コードをPython 3に翻訳したところです。

keys = d.keys()
for (i, res) in enumerate(some_list):
    k = keys[i]
    # ...

これはきれいではありませんが、それほど悪くはありません。最初、私はそれを巨大なものに置き換えようとしていました

    k = next(itertools.islice(iter(keys), i, None))

私が気づく前に、これはすべてはるかによく書かれています

for (k, res) in zip(d.keys(), some_list):

これは問題なく動作します。

他の多くの場合、辞書キーの位置による索引付けは回避できると思います。辞書はPython 3.7で順序付けされていますが、これに依存することはあまりよくありません。上記のコードsome_listは、のコンテンツがのコンテンツから最近作成されたためにのみ機能しdます。

disk_keysインデックスで要素にアクセスする必要がある場合は、コードをよく確認してください。おそらく必要はありません。


0

これを試して

keys = [next(iter(x.keys())) for x in test]
print(list(keys))

結果は次のようになります。['foo'、 'hello']

あなたはここでより多くの可能な解決策を見つけることができます。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.