web-dev-qa-db-ja.com

辞書の値でキーを取得する

私はDictionaryで年齢を調べ、一致する名前を表示する関数を作りました。

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

私は自分の名前を表示する方法がわからないだけで年齢を比較して見つける方法を知っています。さらに、5行目でKeyErrorを取得しています。これは正しくないことはわかっていますが、逆方向に検索する方法を理解することはできません。

449
user998316

なにもない。 dictはこのように使われることを意図していません。

for name, age in dictionary.items():    # for name, age in dictionary.iteritems():  (for Python 2.x)
    if age == search_age:
        print(name)
403
Cat Plus Plus
mydict = {'george':16,'amber':19}
print mydict.keys()[mydict.values().index(16)] # Prints george

あるいはPython 3.xでは:

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

基本的に、それはリスト中の辞書の値を分離し、あなたが持っている値の位置を見つけ、そしてその位置のキーを得る。

Python 3のkeys().values()の詳細: Python:dictから値の一覧を取得するための最も簡単な方法はありますか?

450
Stênio Elson

ageの両方の名前が必要な場合は、.items()を使用してください。これにより、キーとなる(key, value)タプルが得られます。

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

forループの中で、Tupleを2つの別々の変数に展開してから、年齢に合わせることができます。

また、一般的に年齢で検索する予定で、同じ年齢の人が2人いない場合は、辞書を逆にすることも検討する必要があります。

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

そうすることであなたは年齢の名前を調べることができます

mydict[search_age]

mydictは組み込み型の名前であるため、listではなくlistと呼んでいます。その名前を他のものに使用しないでください。

あなたは一行で与えられた年齢を持つすべての人々のリストを得ることさえできます:

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

または各年齢に1人の人しかいない場合:

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

その年齢の誰もいない場合、これはあなたにNoneを与えるだけです。

最後に、dictが長く、Python 2を使用している場合は、Cat Plus Plusが答えたように.iteritems()の代わりに.items()を使用することを検討する必要があります。

202
agf

どの方法が最も速いのか、そしてどのようなシナリオでそれを指摘するのが面白いかと思いました。

これが私が実行したいくつかのテストです(2012 MacBook Pro)。

>>> 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)]

各メソッドのprofile.run()からの結果は100000回:

方法1:

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

方法2:

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

方法3:

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

したがって、これは小さな辞書では方法1が最も速いことを示しています。これは、方法2のようなすべての一致とは対照的に、最初の一致を返すためです(下記の注を参照)。


興味深いことに、私が持っている辞書で同じテストを2700のエントリで実行すると、かなり異なる結果が得られます(今回は10000回実行します)。

方法1:

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

方法2:

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

方法3:

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

だからここでは、方法3ははるか速いです。ちょうどあなたの辞書のサイズがあなたがどの方法を選ぶかに影響を与えることを示すために行きます。

メモ:方法2はallnamesのリストを返しますが、方法1と3は最初の一致のみを返します。メモリ使用量を考慮していません。 3は2つの追加リスト(keys()とvalues())を作成し、それらをメモリに格納します。

58
Patrick

1行バージョン:(iは古い辞書、pは逆辞書です)

説明:i.keys()とi.values()はそれぞれ辞書のキーと値を持つ2つのリストを返します。 Zip関数にはリストを結合して辞書を作成する機能があります。

警告:これは値がハッシュ可能で一意の場合にのみ機能します。

p = dict(Zip(i.values(),i.keys()))
38
fanny
a = {'a':1,'b':2,'c':3}
{v:k for k, v in a.items()}[1]

以上

{k:v for k, v in a.items() if v == 1}
22
Jelen
lKey = [key for key, value in lDictionary.iteritems() if value == lValue][0]
19
faham

dict.keys()dict.values() 、および list.index() メソッドを使用してキーを取得できます。以下のコードサンプルを参照してください。

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

これが私のこの問題に対する考え方です。 :)私はPythonの学習を始めたばかりなので、これを呼び出します。

「初心者にも理解できる」ソリューション。

#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
Deithrian

値でキーを見つけたい場合は、辞書内包表記を使用してルックアップ辞書を作成し、それを使用して値からキーを検索できます。

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

私はこの 答え を見つけました。

より明確にするために、辞書のキーと値を逆にすることができます。これは、 here のようにキーと値をキーにすることです。

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

または

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

これは本質的にこの他のものと同じです 答え

6
Rafael Valero

辞書を逆にするには、このワンライナーを試してください。

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

ここで、recover_keyは辞書と辞書で見つける値を取ります。次に辞書内のキーをループしてvalueのキーと比較し、その特定のキーを返します。

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

Pandasの使用を検討してください。 William McKinneyの "Python for Data Analysis"に述べられているように

Seriesについて考えるもう1つの方法は、インデックス値からデータ値へのマッピングであるため、固定長の順序付き辞書としてです。それはあなたが辞書を使うかもしれない多くの文脈で使用することができます。

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

シリーズをクエリするには、次の手順に従います。

lookup_list[lookup_list.values == 19]

どの収率:

Out[1]: 
amber    19
dtype: int64

もしあなたが答えをリストに変換する出力で他に何かする必要があるなら、役に立つかもしれません:

answer = lookup_list[lookup_list.values == 19].index
answer = pd.Index.tolist(answer)
6
Axel
get_key = lambda v, d: next(k for k in d if d[k] is v)
4
Brett
for name in mydict.keys():
    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
4
patrick

それは答えられました、しかしそれは空想の 'map/reduce'使用でされることができました、例えば:

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()))
4
formiaczek
def get_Value(dic,value):
    for name in dic:
        if dic[name] == value:
            del dic[name]
            return name
4
Raj Damani

私はこれが役立つかもしれないと思います...

for key in list:
   if list[key] == search_value:
       return key
3
Nat

値を「調べる」ことによってリスト内のキーを見つける簡単な方法はありません。ただし、値を知っている場合は、キーを繰り返し使用して、要素ごとに辞書内の値を調べることができます。 Dが辞書オブジェクトであるD [element]が検索しようとしているキーと等しい場合、いくつかのコードを実行できます。

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
Ethan

私はこれが古くなっているのを知っています、しかしあなたはリスト内包を使ってあなたの検索年齢でリストの中のすべての人々を非常に簡単に見つけることができました。

ages = {'george':16,'amber':19}
search = 16
print([name for (name, age) in ages.items() if age == search])
3
fr1eza

これが私の考えです。念のため、複数の結果を表示するのに便利です。だから私は同様にリストを追加しました 

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)

以上です... 

3
user3649211

あなたは辞書とその辞書の逆を使う必要があります。それはあなたが別のデータ構造を必要とすることを意味します。あなたがpython 3を使っているなら、enumモジュールを使いますが、あなたがpython 2.7を使っているなら、python 2用にバックポートされたenum34を使います。

例:

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
Hamid FzM

時々int()が必要になるかもしれません:

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
2
wzbozon

Cat Plus Plusは、これは辞書の使い方を意図したものではないと述べました。これが理由です:

辞書の定義は、数学におけるマッピングの定義と似ています。この場合、辞書はK(キーのセット)からV(値)へのマッピングですが、その逆はありません。辞書を間接参照した場合、返される値は1つだけになります。しかし、異なるキーが同じ値にマッピングされることは完全に合法です。例えば:

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

対応する値でキーを調べると、基本的には辞書が反転しています。しかし、マッピングは必ずしも可逆的ではありません。この例では、v1に対応するキーを尋ねると、k1またはk3になります。あなたは両方を返すべきですか?最初のものだけが見つかりましたか?それがindexof()が辞書に対して未定義である理由です。

あなたがあなたのデータを知っていれば、あなたはこれをすることができます。しかし、APIは任意の辞書が可逆であると仮定することはできません、したがってそのような操作の欠如。

2
Dan Ahlquist
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.

複数回出現する場合は、次のように使用します。

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

辞書にアクセスして、あなたが望むことをするのです。

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

もちろん、あなたの名前はそれほど古く、年齢を印刷するように見えますが、名前は印刷されます。あなたは名前でアクセスしているので、次のように書くと理解しやすくなります。

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

いっそのこと: 

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
Surest Texas
d= {'george':16,'amber':19}

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

出力は以下のとおりです。

-> prints george
1
Jeroen

すでに回答されていますが、何人かの人々が辞書を逆にすることを述べたので、ここであなたはそれを1行(1:1マッピングを仮定して)でする方法といくつかの様々なperfデータです:

python 2.6:

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

2.7+:

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

1:1ではないと思われる場合でも、数行で妥当な逆マッピングを作成できます。

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

これはどれくらい遅いですか?単純な検索よりは遅くなりますが、思ったほど遅くはありません - 「ストレート」な100000エントリの辞書では、「高速」な検索(つまり、キーの早いほうにあるべき値を探す)辞書全体を逆にするよりも約10倍速く、(最後に向かって)「遅い」検索で約4倍から5倍速くなりました。それで、せいぜい10回のルックアップの後、それはそれ自身のために支払われます。 

2番目のバージョン(アイテムごとのリスト付き)は、単純バージョンの約2.5倍かかります。

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

Ifilterについても興味深い結果がいくつかありました。理論的には、iferterはもっと速いはずです。itervalues()を使うことができ、おそらく値リスト全体を作成/通過する必要がないからです。実際には、結果は...奇妙でした...

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

そのため、オフセットが小さい場合は、以前のバージョンよりも劇的に高速になりました(以前のケースでは2.36 * u * S対最小1.48 * m * S)。ただし、リストの末尾近くの大きなオフセットの場合、それは劇的に遅くなりました(15.1ミリ秒対同じ1.48ミリ秒)。ローエンドでの小さな節約は、ハイエンドでのコストに見合う価値はありません、私見。 

1
Corley Brigman

これを行う簡単な方法は次のとおりです。

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

これは、search_ageに一致する値を持つキーのリストを返します。必要に応じて、「list == search_age」を他の条件ステートメントに置き換えることもできます。

0
Meilin He

Keydictは、次の方法で取得できます。

def getKey(dict,value):
     return [key for key in dict.keys() if (dict[key] == value)]
0
Sakhri Houssem

私は、答えが重複しないようにできる限り多くの解決策を読もうとしました。しかし、リストに含まれる値を辞書で扱っていて、特定の要素を持つキーを取得したい場合は、次のようにします。

d = {'Adams': [18, 29, 30],
     'Allen': [9, 27],
     'Anderson': [24, 26],
     'Bailey': [7, 30],
     'Baker': [31, 7, 10, 19],
     'Barnes': [22, 31, 10, 21],
     'Bell': [2, 24, 17, 26]}

それでは、値に24を持つ名前を見つけましょう。

for key in d.keys():    
    if 24 in d[key]:
        print(key)

これは複数の値でも機能します。 

0
cyber-math

私の答えはlambdafilterだけです。

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

これは、Python 2とPython 3の両方で機能する解決策です。

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

[search_age]までの部分は逆辞書を構築します(値はキーであり、逆もまた同じです)。

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

あるいはもっと一般的にはあなたの一人以上のリストに対して年齢による名前の検索方法を作成するファクトリ

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]

だからあなたはできるようになるでしょう:

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

前者は定義済みの型なので、私はlistages_by_nameに名前変更したことに注意してください。

0
eold