การเข้าถึงองค์ประกอบ dict_keys โดยดัชนีใน Python3


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()ส่งคืนชุดเช่น view object ไม่ใช่ list (ดังนั้นจึงไม่สามารถสร้างดัชนีได้) ใช้keys = list(test)
Ashwini Chaudhary

เมื่อฉันทำรายการ (something_dict) ลำดับทูเปิลจะเป็นแบบสุ่ม: ตัวอย่าง: list ({'foo': 'bar', 'hello': 'world'}) สามารถส่งคืน: list (foo, hello) หรือ list (hello, foo) ทำไมถึงสุ่ม?
fj123x

7
Dicts ไม่มีคำสั่งใด ๆ (ใช้collections.OrderedDictถ้าคุณต้องการคีย์ที่สั่งซื้อ)
Ashwini Chaudhary

การอภิปรายที่น่าสนใจเกี่ยวกับความปลอดภัยของเธรดที่นี่จะกล่าวถึงแนวทางต่างๆในการแก้ปัญหานี้: blog.labix.org/2008/06/27/…
Paul

คำตอบ:


161

เรียกlist()พจนานุกรมแทน:

keys = list(test)

ใน Python 3 dict.keys()เมธอดจะส่งคืนอ็อบเจ็กต์มุมมองพจนานุกรมซึ่งทำหน้าที่เป็นชุด การทำซ้ำในพจนานุกรมโดยตรงจะให้คีย์ด้วยดังนั้นการเปลี่ยนพจนานุกรมเป็นรายการจะทำให้ได้รายการคีย์ทั้งหมด:

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

3
ระวังรายการ (dict.keys ()) ใน Python 3 - Labix Blogอธิบายอย่างชัดเจนว่าปัญหาคืออะไรโดยไม่ต้องให้วิธีแก้ไข ยอดเยี่ยมมาก!
Brandon Bradley

@BrandonBradley: โดยทั่วไปการพูด: การพึ่งพาการกระทำบางอย่างเป็นปรมาณูก็เป็นความคิดที่ไม่ดีอยู่ดีเนื่องจาก Python นั้นมีพลวัตสูงมาก รหัสของคุณสามารถส่งผ่านdictคลาสย่อยได้อย่างง่ายดายตัวอย่างเช่นตำแหน่งที่.keys()จัดการในโค้ด Python (เช่นเธรดสวิตช์สามารถเกิดขึ้นได้)
Martijn Pieters

@BrandonBradley: ขอบคุณสำหรับลิงค์ เฉพาะวิธีแก้ปัญหาจากหนึ่งในความคิดเห็นสำหรับบล็อกนั้นที่ใช้ได้กับฉันใน Python3: sorted (dict.keys ()) ใน Python2 dict.keys () จะส่งคืนรายการของค่าคีย์
Good Will

2
@GoodWill: sorted(dict)จะทำสิ่งเดียวกันแน่นอน; จัดทำรายการคีย์ตามลำดับที่จัดเรียง list(dict)จะให้รายการตามลำดับพจนานุกรม
Martijn Pieters

1
หรือจะใช้keys = [*test]
Alex78191

60

ไม่ใช่คำตอบที่สมบูรณ์ แต่อาจเป็นคำแนะนำที่มีประโยชน์ หากเป็นรายการแรกที่คุณต้องการ * จริงๆ

next(iter(q))

เร็วกว่ามาก

list(q)[0]

สำหรับคำสั่งขนาดใหญ่เนื่องจากสิ่งทั้งหมดไม่จำเป็นต้องเก็บไว้ในหน่วยความจำ

สำหรับรายการ 10.000.000 ฉันพบว่ามันเร็วกว่าเกือบ 40.000 เท่า

* รายการแรกในกรณีที่ dict เป็นเพียงไอเท็มสุ่มหลอกก่อนPython 3.6 (หลังจากนั้นจะได้รับคำสั่งในการใช้งานมาตรฐานแม้ว่าจะไม่แนะนำให้พึ่งพาก็ตาม)


5
นี่เป็นหนึ่งในปัญหาใหญ่ที่สุดของฉันที่ทุกอย่างกลายเป็นตัววนซ้ำใน Py3 มีประสิทธิภาพมากกว่าอย่างแน่นอน แต่กรณีการใช้งานจำนวนมากกลายเป็น "มลทิน" และซับซ้อนโดยไม่มีเหตุผล ตัวอย่างเช่นเหตุใดจึงไม่รองรับการสร้างดัชนีบนตัววนซ้ำโดยไม่จำเป็นต้องสูญเสียประสิทธิภาพ
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', 'สวัสดี']

คุณสามารถหาคำตอบที่เป็นไปได้มากขึ้นที่นี่

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.