2012-05-08 25 views
57

tôi có:Làm thế nào để lọc các phím từ điển dựa trên các giá trị tương ứng của nó

dictionary = {"foo":12, "bar":2, "jim":4, "bob": 17} 

Tôi muốn để lặp qua từ điển này, nhưng so với giá trị thay vì các phím, vì vậy tôi có thể sử dụng các giá trị trong chức năng khác.

Ví dụ: tôi muốn kiểm tra giá trị từ điển nào lớn hơn 6 và sau đó lưu khóa của chúng trong danh sách. Mã của tôi trông như thế này:

list = [] 
for c in dictionary: 
    if c > 6: 
     list.append(dictionary[c]) 
print list 

và sau đó, trong một thế giới hoàn hảo, list sẽ tính năng tất cả các phím có giá trị lớn hơn 6. Tuy nhiên, vòng lặp for của tôi chỉ lặp qua các phím; Tôi muốn thay đổi điều đó thành giá trị!

Bất kỳ trợ giúp nào được đánh giá cao. cảm ơn bạn

+1

Tiêu đề của câu hỏi này nên được thay đổi kể từ những gì bạn thực sự muốn đạt được (và các câu trả lời phản ánh điều này) lấy các khóa của các giá trị tương ứng trong một từ điển mà một mệnh đề nhất định là đúng. Một cái gì đó như "Làm thế nào để lọc các khóa từ điển dựa trên các giá trị tương ứng của nó" có thể là một lựa chọn tốt hơn. – glarrain

Trả lời

81
>>> d = {"foo": 12, "bar": 2, "jim": 4, "bob": 17} 
>>> [k for k, v in d.items() if v > 6] # Use d.iteritems() on python 2.x 
['bob', 'foo'] 

Tôi muốn chỉ cập nhật câu trả lời này cũng để giới thiệu những giải pháp bởi @glarrain mà tôi thấy mình có khuynh hướng sử dụng ngày nay.

[k for k in d if d[k] > 6] 

này là hoàn toàn tương thích chéo và không đòi hỏi một sự thay đổi khó hiểu từ .iteritems (.iteritems tránh tiết kiệm một danh sách để nhớ về Python 2 được cố định bằng Python 3) để .items.

@ Prof.Falken đề cập đến một giải pháp cho vấn đề này

from six import iteritems 

mà hiệu quả sửa chữa các vấn đề tương thích chéo NHƯNG đòi hỏi bạn phải tải về gói six

Tuy nhiên tôi sẽ không hoàn toàn đồng ý với @glarrain rằng giải pháp này có thể đọc được nhiều hơn, đó là cho cuộc tranh luận và có thể chỉ là một sở thích cá nhân mặc dù Python được cho là chỉ có 1 cách để làm điều đó. Theo ý kiến ​​của tôi, điều đó phụ thuộc vào tình huống (ví dụ: bạn có thể có tên từ điển dài mà bạn không muốn nhập hai lần hoặc bạn muốn đặt giá trị cho một tên dễ đọc hơn hoặc một số lý do khác)

Một số thời gian thú vị :

Trong Python 2, giải pháp thứ 2 nhanh hơn, trong Python 3 chúng gần như hoàn toàn bằng nhau ở tốc độ thô.


$ python -m timeit -s 'd = {"foo": 12, "bar": 2, "jim": 4, "bob": 17};' '[k for k, v in d.items() if v > 6]' 
1000000 loops, best of 3: 0.772 usec per loop 
$ python -m timeit -s 'd = {"foo": 12, "bar": 2, "jim": 4, "bob": 17};' '[k for k, v in d.iteritems() if v > 6]' 
1000000 loops, best of 3: 0.508 usec per loop 
$ python -m timeit -s 'd = {"foo": 12, "bar": 2, "jim": 4, "bob": 17};' '[k for k in d if d[k] > 6]' 
1000000 loops, best of 3: 0.45 usec per loop 

$ python3 -m timeit -s 'd = {"foo": 12, "bar": 2, "jim": 4, "bob": 17};' '[k for k, v in d.items() if v > 6]' 
1000000 loops, best of 3: 1.02 usec per loop 
$ python3 -m timeit -s 'd = {"foo": 12, "bar": 2, "jim": 4, "bob": 17};' '[k for k in d if d[k] > 6]' 
1000000 loops, best of 3: 1.02 usec per loop 

Tuy nhiên đây chỉ là những thử nghiệm cho từ điển nhỏ, trong từ điển khổng lồ Tôi khá chắc chắn rằng không có một chìa khóa tra cứu từ điển (d[k]) sẽ làm cho .items nhanh hơn nhiều. Và điều này dường như là trường hợp

$ python -m timeit -s 'd = {i: i for i in range(-10000000, 10000000)};' -n 1 '[k for k in d if d[k] > 6]' 
1 loops, best of 3: 1.75 sec per loop 
$ python -m timeit -s 'd = {i: i for i in range(-10000000, 10000000)};' -n 1 '[k for k, v in d.iteritems() if v > 6]' 
1 loops, best of 3: 1.71 sec per loop 
$ python3 -m timeit -s 'd = {i: i for i in range(-10000000, 10000000)};' -n 1 '[k for k in d if d[k] > 6]' 
1 loops, best of 3: 3.08 sec per loop 
$ python3 -m timeit -s 'd = {i: i for i in range(-10000000, 10000000)};' -n 1 '[k for k, v in d.items() if v > 6]' 
1 loops, best of 3: 2.47 sec per loop 
+0

+1. Chắc chắn là câu trả lời hay nhất IMHO. –

+5

Đối với python 2.x, 'd.iteritems()' sẽ là AFAIK tốt hơn. – hochl

+0

Rực rỡ, cảm ơn bạn! – Hoops

4

Làm thế nào về điều này:

dictionary = {"foo":12, "bar":2, "jim":4, "bob": 17} 
for val in dictionary.values(): 
    # do something 
+0

Nếu OP không nhớ, tôi muốn xóa câu trả lời của tôi. @ jamylak của nó chắc chắn là con đường để đi. –

36

Để chỉ nhận các giá trị, sử dụng dictionary.values()

Để có được cặp giá trị quan trọng, sử dụng dictionary.items()

10

Sử dụng items hoặc iteritems trên từ điển. Một cái gì đó như:

list = [] 
for k, v in dictionary.iteritems(): 
    if v > 6: 
    list.append(k) 
print list 
2

Điều đó phụ thuộc vào việc bạn muốn sửa đổi từ điển (thêm hoặc xóa các mục) hay không. Nếu không thì bạn có thể thử:

for value in dictionary.itervalues(): #this returns a generator 
    print "do something with the value" 

Ngoài ra nếu bạn sửa đổi từ điển mà bạn nên lặp trên một bản sao của các giá trị:

for value in dictionary.values(): #this returns a list of values 
    print "do something with the value" 

Nếu bạn muốn cả khóa và giá trị bạn có thể lặp lại trên cặp sử dụng dictionary.iteritems() hay dictionary.items()

2

tôi nghĩ rằng cách tốt nhất để làm điều này (xem xét chuyển đổi sang Python 3) là

>>> mydict = {'foo': 12, 'bar': 2, 'jim': 4, 'bob': 17} 
>>> [k for k in mydict if mydict[k] > 6] 
['bob', 'foo'] 

Tiêu chí cho "tốt nhất" là dễ đọc.

(Disclaimer: Câu trả lời của tôi là có trụ sở tại câu trả lời Alex Martelli cho câu hỏi khác https://stackoverflow.com/a/3744713/556413 và @ của jamylak cho câu hỏi này)

Các vấn đề liên quan