Truy cập phần tử dict_keys theo chỉ mục trong Python3


131

Tôi đang cố gắng truy cập phần tử của dict_key theo chỉ mục của nó:

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

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

tôi muốn có được foo .

giống với:

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

Tôi có thể làm cái này như thế nào?


9
Trong py3.x dict.keys()trả về một tập hợp như đối tượng xem, không liệt kê (vì vậy, không thể lập chỉ mục). Sử dụngkeys = list(test)
Ashwini Chaudhary

khi tôi thực hiện danh sách (Something_dict), thứ tự tuple là ngẫu nhiên: ví dụ: list ({'foo': 'bar', 'hello': 'world'}) có thể trả về: list (foo, hello) hoặc list (hello, foo), tại sao điều này là ngẫu nhiên?
fj123x

7
Dicts không có bất kỳ thứ tự nào . (Sử dụng collections.OrderedDictnếu bạn muốn các phím được đặt hàng)
Ashwini Chaudhary

Thảo luận thú vị về an toàn luồng ở đây thử nghiệm các cách tiếp cận khác nhau để giải quyết vấn đề này: blog.labix.org/2008/06/27/ mẹo
Paul

Câu trả lời:


161

Gọi list()từ điển thay thế:

keys = list(test)

Trong Python 3, dict.keys()phương thức trả về một đối tượng xem từ điển , hoạt động như một tập hợp. Lặp lại trực tiếp từ điển cũng mang lại các khóa, do đó, việc biến một từ điển thành một danh sách dẫn đến một danh sách tất cả các khóa:

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

3
Xem ra danh sách (dict.keys ()) trong Python 3 - Blog Labix giải thích rõ ràng vấn đề là gì mà không cung cấp giải pháp. Thật tuyệt vời!
Brandon Bradley

@BrandonBradley: nói chung: dựa vào một số hành động nhất định là nguyên tử là một ý tưởng tồi, vì Python rất năng động. Mã của bạn có thể dễ dàng được thông qua một dictlớp con, ví dụ, nơi .keys()được xử lý trong mã Python (ví dụ: chuyển đổi luồng có thể diễn ra).
Martijn Pieters

@BrandonBradley: cảm ơn vì đường link. Chỉ có giải pháp từ một trong những bình luận cho blog đó hoạt động với tôi trong Python3: sort (dict.keys ()). Trong Python2, dict.keys () sẽ trả về danh sách các giá trị chính.
Thiện chí

2
@ GoodWill: sorted(dict)sẽ làm điều tương tự chính xác; tạo một danh sách các khóa theo thứ tự sắp xếp. list(dict)sẽ cung cấp cho bạn danh sách theo thứ tự từ điển.
Martijn Pieters

1
hoặc có thể sử dụngkeys = [*test]
Alex78191

59

Không phải là một câu trả lời đầy đủ nhưng có lẽ là một gợi ý hữu ích. Nếu nó thực sự là mục đầu tiên bạn muốn *, thì

next(iter(q))

nhanh hơn nhiều

list(q)[0]

đối với các thiết bị lớn, vì toàn bộ không phải lưu trữ trong bộ nhớ.

Đối với 10.000.000 mặt hàng, tôi thấy nó nhanh hơn gần 40.000 lần.

* Mục đầu tiên trong trường hợp dict chỉ là mục giả ngẫu nhiên trước Python 3.6 (sau đó, nó được yêu cầu trong triển khai tiêu chuẩn, mặc dù không nên dựa vào nó).


5
Đây luôn là một trong những vấn đề lớn nhất của tôi với mọi thứ trở thành các trình vòng lặp trong Py3. Nó chắc chắn hiệu quả hơn, nhưng rất nhiều trường hợp sử dụng trở nên "ô uế" và phức tạp mà không có lý do. Ví dụ, tại sao họ không thể chỉ hỗ trợ lập chỉ mục trên trình vòng lặp mà không nhất thiết bị mất hiệu năng?
Ehsan Kia

2

Tôi muốn cặp "khóa" & "giá trị" của một mục từ điển đầu tiên. Tôi đã sử dụng mã sau đây.

 key, val = next(iter(my_dict.items()))

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

Cách thông thường để gắn các khóa vào danh sách được xác định tĩnh và sau đó lập chỉ mục cho cùng


2
Nó không sai, nhưng tại sao không ls = list(test.keys())? Tôi thấy nó đơn giản hơn.
Valentino ngày

Vâng, điều này là hiệu quả hơn. Tôi đã viết điều này chỉ để hiển thị khả năng đọc.
pranav dua

0

Trong nhiều trường hợp, đây có thể là một vấn đề XY . Tại sao bạn lập chỉ mục các khóa từ điển của bạn theo vị trí? Bạn có thực sự cần? Cho đến gần đây, từ điển thậm chí không được đặt hàng trong Python, vì vậy việc truy cập phần tử đầu tiên là tùy ý.

Tôi vừa dịch một số mã Python 2 sang Python 3:

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

Điều đó không đẹp, nhưng cũng không tệ lắm. Lúc đầu, tôi chuẩn bị thay thế nó bằng sự quái dị

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

trước khi tôi nhận ra đây là một văn bản tốt hơn nhiều

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

mà hoạt động tốt

Tôi tin rằng trong nhiều trường hợp khác, việc lập chỉ mục các khóa từ điển theo vị trí có thể tránh được. Mặc dù từ điển được đặt hàng trong Python 3.7, nhưng dựa vào đó là không đẹp. Mã ở trên chỉ hoạt động vì nội dung của some_listgần đây đã được sản xuất từ ​​nội dung của d.

Hãy nhìn kỹ vào mã của bạn nếu bạn thực sự cần truy cập một disk_keysphần tử theo chỉ mục. Có lẽ bạn không cần.


0

Thử cái này

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

Kết quả trông như thế này. ['foo', 'xin chào']

Bạn có thể tìm thấy nhiều giải pháp khả thi hơn ở đây .

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.