Nhận khóa theo giá trị trong từ điển


632

Tôi đã thực hiện một chức năng sẽ tìm kiếm độ tuổi trong một Dictionaryvà hiển thị tên phù hợp:

dictionary = {'george' : 16, 'amber' : 19}
search_age = raw_input("Provide age")
for age in dictionary.values():
    if age == search_age:
        name = dictionary[age]
        print name

Tôi biết cách so sánh và tìm tuổi tôi chỉ không biết cách thể hiện tên của người đó. Ngoài ra, tôi nhận được KeyErrorvì dòng 5. Tôi biết điều đó không đúng nhưng tôi không thể tìm ra cách làm cho nó tìm kiếm ngược.



Bạn sẽ tìm thấy một từ dựa trên định nghĩa của nó trong một từ điển? ĐẠO ĐỨC.
Jossie Calderon

Câu trả lời:


563

Chẳng có ai. dictkhông có ý định được sử dụng theo cách này.

dictionary = {'george': 16, 'amber': 19}
search_age = input("Provide age")
for name, age in dictionary.items():  # for name, age in dictionary.iteritems():  (for Python 2.x)
    if age == search_age:
        print(name)

137
Trong Python 3.x list.items()thay vì list.iteritems()nên được sử dụng
Yuriy Petrovskiy

63
Tôi không đồng ý ... câu trả lời của agf dưới đây mang tính xây dựng hơn. Một trường hợp sử dụng hoàn toàn hợp lý không phải là "ngoài ý muốn" (dù sao danh sách cũng phù hợp với trường hợp sử dụng như vậy). A dictcó thể cho nhiều thứ vào những thời điểm khác nhau; các khóa và giá trị có ý nghĩa rõ ràng, tất nhiên, nhưng " dictcác mục có giá trị nhất định" là một yêu cầu hoàn toàn hợp lý. Đề xuất sử dụng danh sách các cặp sẽ loại bỏ bối cảnh rằng một mục là ' định nghĩa ' từ mục kia, ví dụ như trong danh sách tham số ...
Louis Maddox

1
Tôi không đồng ý với câu trả lời này. Thực tế đó là một khả năng, như thể hiện trong câu trả lời của Stênio Elson, không ngụ ý rằng nó không có ý định sử dụng như vậy. Không hữu ích chút nào.
Tropicalrambler

Bạn sẽ tìm thấy một từ trong một từ điển dựa trên định nghĩa của nó? ĐẠO ĐỨC. @Tropicalrambler
Jossie Calderon

Mặc dù bạn có một điểm mà việc sử dụng tiêu chuẩn cho từ điển là tìm kiếm định nghĩa của từ với word = key và định nghĩa = value, ngôn ngữ lập trình ngày nay cho phép bạn tìm kiếm theo giá trị nếu cần thiết. Nếu bạn đang làm việc với một đối tượng cặp khóa: value (gọi nó là từ điển, tuple, bất kỳ tên nào cho bất kỳ ngôn ngữ nào). Trong python, thực tế là bạn vẫn có thể lập chỉ mục thông qua các giá trị của cấu trúc để tìm ra các khóa tương ứng.
Tropicalrambler

599
mydict = {'george': 16, 'amber': 19}
print mydict.keys()[mydict.values().index(16)]  # Prints george

Hoặc trong Python 3.x:

mydict = {'george': 16, 'amber': 19}
print(list(mydict.keys())[list(mydict.values()).index(16)])  # Prints george

Về cơ bản, nó phân tách các giá trị của từ điển trong một danh sách, tìm vị trí của giá trị bạn có và lấy khóa ở vị trí đó.

Thông tin thêm về keys().values()trong Python 3: Làm cách nào tôi có thể nhận danh sách các giá trị từ dict?


23
Trông thật tuyệt nhưng nó có hoạt động không? Ý tôi là, làm list.keys()list.values()chức năng tạo các mục theo cùng một thứ tự?
iskorum

17
Vâng, họ được đảm bảo là nhất quán. Ngoài ra, thứ tự được đảm bảo không thay đổi qua các lần lặp miễn là từ điển không bị sửa đổi.
Veedrac

9
Đây có vẻ là một giải pháp tốt nhưng chỉ mục chỉ đưa ra một giá trị đúng, vì vậy nếu bạn có nhiều giá trị bằng nhau, thì nó sẽ trả về nhiều khóa phải không?
James Sapam

12
@ArtOfWarfare docs.python.org/3/library/stdtypes.html#dict-views , "Nếu khóa, giá trị và quan điểm mục được lặp trên không có sửa đổi can thiệp vào từ điển, thứ tự các mặt hàng sẽ trực tiếp tương ứng."
Veedrac

5
@sinekonata: Nó vẫn thực hiện một vòng lặp đắt tiền dưới mui xe; vòng lặp chỉ được ẩn bên trong indexphương thức.
user2357112 hỗ trợ Monica

252

Nếu bạn muốn cả tên tuổi, bạn nên sử dụng .items()cung cấp cho bạn (key, value)bộ khóa chính :

for name, age in mydict.items():
    if age == search_age:
        print name

Bạn có thể giải nén bộ dữ liệu thành hai biến riêng biệt ngay trong forvòng lặp, sau đó khớp với độ tuổi.

Bạn cũng nên xem xét đảo ngược từ điển nếu bạn thường tìm kiếm theo độ tuổi và không có hai người có cùng độ tuổi:

{16: 'george', 19: 'amber'}

để bạn có thể tra cứu tên cho một độ tuổi chỉ bằng cách làm

mydict[search_age]

Tôi đã gọi nó mydictthay listvì vì listlà tên của loại tích hợp và bạn không nên sử dụng tên đó cho bất kỳ thứ gì khác.

Bạn thậm chí có thể nhận được danh sách tất cả những người có độ tuổi nhất định trong một dòng:

[name for name, age in mydict.items() if age == search_age]

hoặc nếu chỉ có một người với mỗi độ tuổi:

next((name for name, age in mydict.items() if age == search_age), None)

sẽ chỉ cho bạn Nonenếu không có ai ở độ tuổi đó.

Cuối cùng, nếu dictthời gian dài và bạn đang sử dụng Python 2, bạn nên cân nhắc sử dụng .iteritems()thay vì .items()như Cat Plus Plus đã làm trong câu trả lời của mình, vì nó không cần phải tạo một bản sao của danh sách.


9
Đúng, nhưng nếu bạn định thực hiện tìm kiếm tuyến tính, bạn cũng có thể thay thế dictbằng danh sách các cặp.
Fred Foo

9
Trừ khi hành động thông thường của bạn là tìm kiếm theo tuổi, trong trường hợp đó là một dictý nghĩa.
agf

2
Có vẻ kỳ lạ khi cho rằng chỉ có một người với mỗi độ tuổi, trong khi mặt khác, việc mỗi người có một độ tuổi là hoàn toàn hợp lý.
Dannid

@Dannid Có, nhưng vấn đề có thể dễ dàng khái quát. Ví dụ: bạn có thể có một bảng tra cứu với các khóa duy nhất và các giá trị duy nhất tương ứng của chúng. Sau đó, bạn có thể tra cứu mọi thứ đối xứng value --> keyhoặckey --> value
pfabri

68

Tôi nghĩ sẽ rất thú vị khi chỉ ra phương pháp nào là nhanh nhất và trong kịch bản nào:

Đây là một số thử nghiệm tôi đã chạy (trên MacBook Pro 2012)

>>> def method1(list,search_age):
...     for name,age in list.iteritems():
...             if age == search_age:
...                     return name
... 
>>> def method2(list,search_age):
...     return [name for name,age in list.iteritems() if age == search_age]
... 
>>> def method3(list,search_age):
...     return list.keys()[list.values().index(search_age)]

Kết quả từ profile.run()mỗi phương pháp 100000 lần:

Cách 1:

>>> profile.run("for i in range(0,100000): method1(list,16)")
     200004 function calls in 1.173 seconds

Cách 2:

>>> profile.run("for i in range(0,100000): method2(list,16)")
     200004 function calls in 1.222 seconds

Cách 3:

>>> profile.run("for i in range(0,100000): method3(list,16)")
     400004 function calls in 2.125 seconds

Vì vậy, điều này cho thấy rằng đối với một lệnh nhỏ, phương pháp 1 là nhanh nhất. Điều này rất có thể bởi vì nó trả về trận đấu đầu tiên, trái ngược với tất cả các trận đấu như phương pháp 2 (xem ghi chú bên dưới).


Thật thú vị, thực hiện các bài kiểm tra tương tự trên một dict tôi có với 2700 mục, tôi nhận được kết quả khá khác nhau (lần này chạy 10000 lần):

Cách 1:

>>> profile.run("for i in range(0,10000): method1(UIC_CRS,'7088380')")
     20004 function calls in 2.928 seconds

Cách 2:

>>> profile.run("for i in range(0,10000): method2(UIC_CRS,'7088380')")
     20004 function calls in 3.872 seconds

Cách 3:

>>> profile.run("for i in range(0,10000): method3(UIC_CRS,'7088380')")
     40004 function calls in 1.176 seconds

Vì vậy, ở đây, phương pháp 3 nhanh hơn nhiều . Chỉ cần đi để hiển thị kích thước của dict của bạn sẽ ảnh hưởng đến phương pháp bạn chọn.

Ghi chú: Phương thức 2 trả về danh sách tất cả các tên, trong khi phương thức 1 và 3 chỉ trả về kết quả khớp đầu tiên. Tôi chưa xem xét việc sử dụng bộ nhớ. Tôi không chắc liệu phương thức 3 có tạo thêm 2 danh sách (khóa () và giá trị ()) và lưu trữ chúng trong bộ nhớ hay không.


6
Chỉ là một bản cập nhật: có vẻ như cả dict.values ​​() và dict.keys () đều trả về danh sách tham chiếu các đối tượng từ dict gốc, vì vậy phương thức 3 cũng là phương thức sử dụng ít bộ nhớ nhất (nó chỉ tạo ra hai đối tượng danh sách mỏng trong đó bao bọc nội dung của các dicts, trong khi những cái khác tạo ra các mục lặp
Patrick

Tôi chỉ muốn tự điểm chuẩn nó, cuộn xuống, bam bạn có nó. Cảm ơn! Về mặt kỹ thuật như bạn đã chỉ ra phương pháp 2 không thực hiện chính xác như 1 và 3 vì nó trả về tất cả các kết quả khớp. sẽ rất tuyệt khi thấy kết quả, ví dụ như quay lại tiếp theo ([..]).
BluBb_mADe

Một lưu ý quan trọng khác để thực hiện là phiên bản Python. Tôi biết một số phiên bản có triển khai phương thức hiệu quả hơn các phiên bản khác.
ArtOfWarfare

@Patrick: tất cả các phương thức sử dụng tham chiếu trực tiếp đến các giá trị và khóa, không có lợi thế về bộ nhớ cho bất kỳ. Ngoại trừ trong Python 3 và .keys()' .values()trả về các lượt xem từ điển, có trọng lượng nhẹ.
Martijn Pieters

53

một phiên bản dòng: (i là một từ điển cũ, p là một từ điển đảo ngược)

giải thích: i.keys()i.values()trả về hai danh sách với các khóa và giá trị của từ điển tương ứng. Hàm zip có khả năng liên kết các danh sách với nhau để tạo ra một từ điển.

p = dict(zip(i.values(),i.keys()))

Cảnh báo: Điều này sẽ chỉ hoạt động nếu các giá trị có thể băm và duy nhất.


Có, điều này sẽ hoạt động: stackoverflow.com/questions/835092/ từ
Mèo Unun

17
... Và khi không có giá trị trùng lặp.
ely

3
Xinh đẹp. Viết nhận xét ở trên, tất nhiên nó chỉ hoạt động khi không có giá trị trùng lặp, nhưng sau đó, câu hỏi bắt đầu chủ đề này đưa ra giả định rằng chúng ta có chức năng một đối một, do đó, giả sử rằng đây là thanh lịch nhất đáp ứng bởi xa.
John Strong

1
mở rộng trên các giá trị có thể băm: nếu các giá trị của bạn là danh sách / bộ chuyển đổi chúng thành tuple để điều này hoạt động (chúng vẫn cần phải là duy nhất).
muon

28
a = {'a':1,'b':2,'c':3}
{v:k for k, v in a.items()}[1]

hoặc tốt hơn

{k:v for k, v in a.items() if v == 1}

5
Điều gì nếu có một khóa khác giữ cùng giá trị của a? Có thể là cách pythonic. Nhưng không phải là một ý tưởng tốt.
7H3 IN5ID3R

điểm tốt, tôi đã thêm giải pháp hoạt động với các giá trị nonunique
Jelen

26
key = next((k for k in my_dict if my_dict[k] == val), None)

Tôi cũng có thể có một 'cái khác' trong cùng dòng này không? Đối với trường hợp khi giá trị của tôi không nằm trong giá trị chính tả
Srishti Gupta

lKey = [k for k, v in lDictionary.iteritems() if v == lValue][0] or 'else-key'
faham

14

Hãy thử một lớp lót này để đảo ngược một từ điển:

reversed_dictionary = dict(map(reversed, dictionary.items()))

1
Điều này làm việc rất tốt cho chương trình mã hóa và giải mã của tôi, cảm ơn bạn!
Christian R


@pfabri ???????
johnaphun

13

Tôi thấy câu trả lời này rất hiệu quả nhưng không dễ đọc cho tôi.

Để làm cho nó rõ ràng hơn, bạn có thể đảo ngược khóa và giá trị của một từ điển. Điều này là làm cho các giá trị khóa và các khóa giá trị, như được thấy ở đây .

mydict = {'george':16,'amber':19}
res = dict((v,k) for k,v in mydict.iteritems())
print(res[16]) # Prints george

hoặc là

mydict = {'george':16,'amber':19}
dict((v,k) for k,v in mydict.iteritems())[16]

mà về cơ bản là giống nhau mà câu trả lời khác này .


12

Nếu bạn muốn tìm khóa theo giá trị, bạn có thể sử dụng mức độ hiểu từ điển để tạo từ điển tra cứu và sau đó sử dụng khóa đó để tìm khóa từ giá trị.

lookup = {value: key for key, value in self.data}
lookup[value]

11

Bạn có thể lấy chìa khóa bằng cách sử dụng dict.keys(), dict.values()list.index()phương pháp, xem mẫu mã bên dưới:

names_dict = {'george':16,'amber':19}
search_age = int(raw_input("Provide age"))
key = names_dict.keys()[names_dict.values().index(search_age)]

2
bạn không sử dụng search_agevar được xác định trên dòng tiếp theo ... Có lẽ bạn nên thay thế valuebằng search_age?
Andersson

2
Tôi gặp lỗi này: đối tượng 'dict_values' không có thuộc tính 'index'
Blue_Elephant

@Blue_Elephant bạn có thể vui lòng cung cấp đoạn mã bạn đã gặp lỗi và phiên bản python (cũng có thể in type(dict_values)sẽ hữu ích)?
Andriy Ivaneyko

9

Đây là nhận của tôi về vấn đề này. :) Tôi mới bắt đầu học Python, vì vậy tôi gọi nó là:

Giải pháp "Có thể hiểu cho người mới bắt đầu".

#Code without comments.

list1 = {'george':16,'amber':19, 'Garry':19}
search_age = raw_input("Provide age: ")
print
search_age = int(search_age)

listByAge = {}

for name, age in list1.items():
    if age == search_age:
        age = str(age)
        results = name + " " +age
        print results

        age2 = int(age)
        listByAge[name] = listByAge.get(name,0)+age2

print
print listByAge

.

#Code with comments.
#I've added another name with the same age to the list.
list1 = {'george':16,'amber':19, 'Garry':19}
#Original code.
search_age = raw_input("Provide age: ")
print
#Because raw_input gives a string, we need to convert it to int,
#so we can search the dictionary list with it.
search_age = int(search_age)

#Here we define another empty dictionary, to store the results in a more 
#permanent way.
listByAge = {}

#We use double variable iteration, so we get both the name and age 
#on each run of the loop.
for name, age in list1.items():
    #Here we check if the User Defined age = the age parameter 
    #for this run of the loop.
    if age == search_age:
        #Here we convert Age back to string, because we will concatenate it 
        #with the person's name. 
        age = str(age)
        #Here we concatenate.
        results = name + " " +age
        #If you want just the names and ages displayed you can delete
        #the code after "print results". If you want them stored, don't...
        print results

        #Here we create a second variable that uses the value of
        #the age for the current person in the list.
        #For example if "Anna" is "10", age2 = 10,
        #integer value which we can use in addition.
        age2 = int(age)
        #Here we use the method that checks or creates values in dictionaries.
        #We create a new entry for each name that matches the User Defined Age
        #with default value of 0, and then we add the value from age2.
        listByAge[name] = listByAge.get(name,0)+age2

#Here we print the new dictionary with the users with User Defined Age.
print
print listByAge

.

#Results
Running: *\test.py (Thu Jun 06 05:10:02 2013)

Provide age: 19

amber 19
Garry 19

{'amber': 19, 'Garry': 19}

Execution Successful!

9
get_key = lambda v, d: next(k for k in d if d[k] is v)

Đẹp một lót. Tuy nhiên, ischỉ nên dùng để thử nghiệm sự bình đẳng của độc thân ( None, True, Falsevv). Việc CPython sử dụng lại chuỗi ký tự (và do đó a = 'foobar'; a is 'foobar'True) là một chi tiết triển khai và không nên dựa vào.
piit79

1
Và thêm một nhận xét: get_keysẽ ném StopIterationnếu giá trị không tồn tại trong từ điển - sẽ tốt hơn nếu sử dụng next(..., None)nó sẽ trả về Nonenếu không tìm thấy giá trị.
piit79

Một sửa đổi nhỏ sẽ hoạt động nếu từ điển không chứa các yếu tố đơn lẻ nhưng thiết lập:get_first_key = lambda v, d: next((k for k in d if (v in d[k] is not None)), None)
siêu tân tinh

7

Cân nhắc sử dụng gấu trúc. Như đã nêu trong "Python cho phân tích dữ liệu" của William McKinney

Một cách khác để suy nghĩ về Sê-ri là một lệnh có độ dài cố định, theo thứ tự, vì nó là ánh xạ của các giá trị chỉ mục đến các giá trị dữ liệu. Nó có thể được sử dụng trong nhiều bối cảnh mà bạn có thể sử dụng một lệnh.

import pandas as pd
list = {'george':16,'amber':19}
lookup_list = pd.Series(list)

Để truy vấn loạt của bạn làm như sau:

lookup_list[lookup_list.values == 19]

Sản lượng nào:

Out[1]: 
amber    19
dtype: int64

Nếu bạn cần làm bất cứ điều gì khác với đầu ra chuyển đổi câu trả lời thành một danh sách có thể hữu ích:

answer = lookup_list[lookup_list.values == 19].index
answer = pd.Index.tolist(answer)

Anh ấy là người tạo ra gấu trúc. Anh ấy thường được gọi là Wes, mặc dù.
Axel

6

Ở đây, recovery_key lấy từ điển và giá trị để tìm trong từ điển. Sau đó, chúng tôi lặp lại các khóa trong từ điển và so sánh với giá trị đó và trả về khóa cụ thể đó.

def recover_key(dicty,value):
    for a_key in dicty.keys():
        if (dicty[a_key] == value):
            return a_key

5

chúng tôi có thể nhận được Keycác dictbằng:

def getKey(dct,value):
     return [key for key in dct if (dct[key] == value)]

4
for name in mydict:
    if mydict[name] == search_age:
        print(name) 
        #or do something else with it. 
        #if in a function append to a temporary list, 
        #then after the loop return the list

1
Sử dụng vòng lặp for và chắp thêm chậm hơn nhiều so với việc hiểu danh sách và nó cũng dài hơn.
alexpinho98

3

nó đã được trả lời, nhưng nó có thể được thực hiện với việc sử dụng 'map / less', ví dụ:

def find_key(value, dictionary):
    return reduce(lambda x, y: x if x is not None else y,
                  map(lambda x: x[0] if x[1] == value else None, 
                      dictionary.iteritems()))

3

Cat Plus Plus đã đề cập rằng đây không phải là cách sử dụng từ điển. Đây là lý do tại sao:

Định nghĩa của một từ điển tương tự như một ánh xạ trong toán học. Trong trường hợp này, một dict là ánh xạ của K (bộ khóa) thành V (các giá trị) - nhưng không phải ngược lại. Nếu bạn hủy đăng ký một lệnh, bạn sẽ nhận được chính xác một giá trị được trả về. Nhưng, việc các khóa khác nhau ánh xạ vào cùng một giá trị là hoàn toàn hợp pháp, ví dụ:

d = { k1 : v1, k2 : v2, k3 : v1}

Khi bạn tra cứu một khóa theo giá trị tương ứng của nó, về cơ bản bạn đang đảo ngược từ điển. Nhưng một bản đồ không nhất thiết là không thể đảo ngược! Trong ví dụ này, yêu cầu khóa tương ứng với v1 có thể mang lại k1 hoặc k3. Bạn có nên trả lại cả hai? Chỉ là người đầu tiên tìm thấy? Đó là lý do tại sao indexof () không được xác định cho từ điển.

Nếu bạn biết dữ liệu của mình, bạn có thể làm điều này. Nhưng một API không thể cho rằng một từ điển tùy ý là không thể đảo ngược, do đó thiếu một hoạt động như vậy.


3

tôi đã bắt nó ở đây. Điều này tốt cho việc hiển thị nhiều kết quả chỉ trong trường hợp bạn cần. Vì vậy, tôi đã thêm danh sách là tốt

myList = {'george':16,'amber':19, 'rachel':19, 
           'david':15 }                         #Setting the dictionary
result=[]                                       #Making ready of the result list
search_age = int(input('Enter age '))

for keywords in myList.keys():
    if myList[keywords] ==search_age:
    result.append(keywords)                    #This part, we are making list of results

for res in result:                             #We are now printing the results
    print(res)

Và đó là ...


3
d= {'george':16,'amber':19}

dict((v,k) for k,v in d.items()).get(16)

Đầu ra như sau:

-> prints george

[k cho k, v trong d.items () nếu v == 16]
auro

3

Không có cách nào dễ dàng để tìm một khóa trong danh sách bằng cách 'tra cứu' giá trị. Tuy nhiên, nếu bạn biết giá trị, lặp qua các phím, bạn có thể tra cứu các giá trị trong từ điển theo yếu tố. Nếu D [phần tử] trong đó D là một đối tượng từ điển, bằng với khóa bạn đang tìm kiếm, bạn có thể thực thi một số mã.

D = {'Ali': 20, 'Marina': 12, 'George':16}
age = int(input('enter age:\t'))  
for element in D.keys():
    if D[element] == age:
        print(element)

3

Bạn cần sử dụng một từ điển và đảo ngược từ điển đó. Nó có nghĩa là bạn cần một cấu trúc dữ liệu khác. Nếu bạn đang ở python 3, hãy sử dụng enummô-đun nhưng nếu bạn đang sử dụng python 2.7, hãy sử dụng enum34lại port cho python 2.

Thí dụ:

from enum import Enum

class Color(Enum): 
    red = 1 
    green = 2 
    blue = 3

>>> print(Color.red) 
Color.red

>>> print(repr(Color.red)) 
<color.red: 1=""> 

>>> type(Color.red) 
<enum 'color'=""> 
>>> isinstance(Color.green, Color) 
True 

>>> member = Color.red 
>>> member.name 
'red' 
>>> member.value 
1 

2
def get_Value(dic,value):
    for name in dic:
        if dic[name] == value:
            del dic[name]
            return name

1
Tại sao phải xóa khóa khỏi từ điển? điều đó không trả lời câu hỏi
Jean-François Fabre

2

Chỉ cần câu trả lời của tôi trong lambdafilter.

filter( lambda x, dictionary=dictionary, search_age=int(search_age): dictionary[x] == search_age  , dictionary )

1

đã được trả lời, nhưng vì một số người đã đề cập đến việc đảo ngược từ điển, đây là cách bạn thực hiện trong một dòng (giả sử ánh xạ 1: 1) và một số dữ liệu hoàn hảo khác nhau:

trăn 2.6:

reversedict = dict([(value, key) for key, value in mydict.iteritems()])

2.7+:

reversedict = {value:key for key, value in mydict.iteritems()}

nếu bạn nghĩ rằng đó không phải là 1: 1, bạn vẫn có thể tạo ánh xạ ngược hợp lý với một vài dòng:

reversedict = defaultdict(list)
[reversedict[value].append(key) for key, value in mydict.iteritems()]

mức độ chậm của nó: chậm hơn so với tìm kiếm đơn giản, nhưng gần như không chậm như bạn nghĩ - trên từ điển nhập 100000 'thẳng', tìm kiếm 'nhanh' (nghĩa là tìm kiếm một giá trị nên có sớm trong các phím) nhanh hơn khoảng 10 lần so với đảo ngược toàn bộ từ điển và tìm kiếm 'chậm' (về cuối) nhanh hơn khoảng 4-5 lần. Vì vậy, sau tối đa khoảng 10 lần tra cứu, nó đã tự trả tiền.

phiên bản thứ hai (với danh sách cho mỗi mục) mất khoảng 2,5 lần miễn là phiên bản đơn giản.

largedict = dict((x,x) for x in range(100000))

# Should be slow, has to search 90000 entries before it finds it
In [26]: %timeit largedict.keys()[largedict.values().index(90000)]
100 loops, best of 3: 4.81 ms per loop

# Should be fast, has to only search 9 entries to find it. 
In [27]: %timeit largedict.keys()[largedict.values().index(9)]
100 loops, best of 3: 2.94 ms per loop

# How about using iterkeys() instead of keys()?
# These are faster, because you don't have to create the entire keys array.
# You DO have to create the entire values array - more on that later.

In [31]: %timeit islice(largedict.iterkeys(), largedict.values().index(90000))
100 loops, best of 3: 3.38 ms per loop

In [32]: %timeit islice(largedict.iterkeys(), largedict.values().index(9))
1000 loops, best of 3: 1.48 ms per loop

In [24]: %timeit reversedict = dict([(value, key) for key, value in largedict.iteritems()])
10 loops, best of 3: 22.9 ms per loop

In [23]: %%timeit
....: reversedict = defaultdict(list)
....: [reversedict[value].append(key) for key, value in largedict.iteritems()]
....:
10 loops, best of 3: 53.6 ms per loop

Cũng có một số kết quả thú vị với ifilter. Về mặt lý thuyết, ifilter nên nhanh hơn, theo đó chúng ta có thể sử dụng itervalues ​​() và có thể không phải tạo / đi qua toàn bộ danh sách giá trị. Trong thực tế, kết quả thật ... kỳ quặc ...

In [72]: %%timeit
....: myf = ifilter(lambda x: x[1] == 90000, largedict.iteritems())
....: myf.next()[0]
....:
100 loops, best of 3: 15.1 ms per loop

In [73]: %%timeit
....: myf = ifilter(lambda x: x[1] == 9, largedict.iteritems())
....: myf.next()[0]
....:
100000 loops, best of 3: 2.36 us per loop

Vì vậy, đối với các độ lệch nhỏ, nó nhanh hơn đáng kể so với bất kỳ phiên bản nào trước đó (2,36 * u * S so với tối thiểu 1,48 * m * S đối với các trường hợp trước). Tuy nhiên, đối với các khoản bù đắp lớn gần cuối danh sách, tốc độ chậm hơn đáng kể (15,1ms so với cùng 1,48mS). Các khoản tiết kiệm nhỏ ở cấp thấp không xứng đáng với chi phí ở cấp cao, imho.


Tôi rất muốn điều này (Reverseedict = defaultdict (list) Reverseedict [value] .append (key) cho khóa, giá trị trong tinyedict.iteritems ()]) hoạt động, nhưng khi sử dụng Python 2.7.3, tôi gặp lỗi cú pháp trên từ 'cho'
slashdottir

đó là những gì bạn thực sự gõ? bạn đang thiếu một cái [trong đó, nếu có. mặt khác, hãy chắc chắn rằng nó nằm trên hai dòng hoặc đặt ;giữa chúng nếu không.
Corley Brigman

1

Đôi khi int () có thể cần thiết:

titleDic = {'Фильмы':1, 'Музыка':2}

def categoryTitleForNumber(self, num):
    search_title = ''
    for title, titleNum in self.titleDic.items():
        if int(titleNum) == int(num):
            search_title = title
    return search_title

1

Đây là một giải pháp hoạt động cả trong Python 2 và Python 3:

dict((v, k) for k, v in list.items())[search_age]

Phần cho đến khi [search_age]xây dựng từ điển ngược (trong đó các giá trị là khóa và ngược lại). Bạn có thể tạo một phương thức trợ giúp sẽ lưu bộ từ điển đảo ngược này như sau:

def find_name(age, _rev_lookup=dict((v, k) for k, v in ages_by_name.items())):
    return _rev_lookup[age]

hoặc thậm chí nói chung là một nhà máy sẽ tạo ra một phương pháp tra cứu tên theo độ tuổi cho một hoặc nhiều danh sách của bạn

def create_name_finder(ages_by_name):
    names_by_age = dict((v, k) for k, v in ages_by_name.items())
    def find_name(age):
      return names_by_age[age]

vì vậy bạn sẽ có thể làm:

find_teen_by_age = create_name_finder({'george':16,'amber':19})
...
find_teen_by_age(search_age)

Lưu ý rằng tôi đổi tên listđể ages_by_namekể từ khi cựu là một loại được xác định trước.


1

Đây là cách bạn truy cập từ điển để làm những gì bạn muốn:

list = {'george': 16, 'amber': 19}
search_age = raw_input("Provide age")
for age in list:
    if list[age] == search_age:
        print age

Tất nhiên, tên của bạn không được như vậy, có vẻ như nó sẽ in một thời đại, nhưng nó KHÔNG in tên. Vì bạn đang truy cập theo tên, nên sẽ dễ hiểu hơn nếu bạn viết:

list = {'george': 16, 'amber': 19}
search_age = raw_input("Provide age")
for name in list:
    if list[name] == search_age:
        print name

Tốt hơn nữa:

people = {'george': {'age': 16}, 'amber': {'age': 19}}
search_age = raw_input("Provide age")
for name in people:
    if people[name]['age'] == search_age:
        print name

1
dictionary = {'george' : 16, 'amber' : 19}
search_age = raw_input("Provide age")
key = [filter( lambda x: dictionary[x] == k  , dictionary ),[None]][0] 
# key = None from [None] which is a safeguard for not found.

Đối với nhiều lần sử dụng:

keys = [filter( lambda x: dictionary[x] == k  , dictionary )]

*** NameError: global name 'dictionary' is not defined
Bishwas Mishra

filter( lambda x, dictionary=dictionary, search_age=int(search_age): dictionary[x] == search_age , dictionary )
Bishwas Mishra
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.