newbie: dictionary - howto get key value

G

G. Völkl

Hello,

I use a dictionary:

phone = {'mike':10,'sue':8,'john':3}

phone['mike'] --> 10

I want to know who has number 3?

3 --> 'john'

How to get it in the python way ?

Thanks
Gerhard
 
D

Diez B. Roggisch

phone = {'mike':10,'sue':8,'john':3}
print [key for key, value in phone.items() if value == 3]

-> ['john']
 
B

bruno modulix

G. Völkl said:
Hello,

I use a dictionary:

phone = {'mike':10,'sue':8,'john':3}

phone['mike'] --> 10

I want to know who has number 3?
3 --> 'john'

Note that you can have many keys with the same value:
phone = {'mike':10,'sue':8,'john':3, 'jack': 3, 'helen' : 10}

How to get it in the python way ?

simplest way I could think of in 30':
def key_from_value(aDict, target):
return [key for key, value in aDict.items() if value==target]

key_from_value(phone, 3)
--> ['john', 'jack']

but this is a linear search, so not very efficient if phone is big.
Then you may want to maintain a reversed index:
(here again, simplest way I could think of)

def rev_index(aDict):
r = {}
for key, value in aDict.items():
if r.has_key(value):
r[value].append(key)
else:
r[value] = [key]
return r
rev_phone = rev_index(phone)
rev_phone
--> {8: ['sue'], 10: ['helen', 'mike'], 3: ['john', 'jack']}

{8: ['sue'], 10: ['helen', 'mike'], 3: ['john', 'jack']}

rev_phone[3]
--> ['john', 'jack']

But now you've got another problem : you need to update the reversed
index each time you modify the dictionary... Which would lead to writing
a class extending dict, maintaining a reversed index, and exposing extra
methods to handle this.

But there may be a better way (someone else ?)
 
T

Tim Roberts

G. Völkl said:
I use a dictionary:

phone = {'mike':10,'sue':8,'john':3}

phone['mike'] --> 10

I want to know who has number 3?

3 --> 'john'

How to get it in the python way ?

If you need to do this a lot, just keep two dictionaries, where the keys in
each are the values in the other.

reversephone = dict( zip( phone.values(), phone.keys() ) )
 
J

John Machin

bruno said:
G. Völkl said:
Hello,

I use a dictionary:

phone = {'mike':10,'sue':8,'john':3}

phone['mike'] --> 10

I want to know who has number 3?
3 --> 'john'

Note that you can have many keys with the same value:
phone = {'mike':10,'sue':8,'john':3, 'jack': 3, 'helen' : 10}

Of course in the real world using given name as a unique key is
ludicrous: 'mike' is a.k.a. 'michael' (or 'mikhail' or 'michele' (which
may be a typo for 'michelle')), and if there's only one 'sue' in your
little black book you need to get out more :)
 
P

Peter Hansen

John said:
Of course in the real world using given name as a unique key is
ludicrous: 'mike' is a.k.a. 'michael' (or 'mikhail' or 'michele' (which
may be a typo for 'michelle')), and if there's only one 'sue' in your
little black book you need to get out more :)

Maybe they're the names of his children... ;-)

Of course, one could have multiple children with the
same name under any or all of the following conditions:

1. insanity (perhaps of the parents or the children?)
2. remarriage (i.e. step-children)
3. sheer forgetfulness
4. laziness ("meet Brian, Brian, and Brian")

This last is the closest I can come to making this post
on-topic... sorry! :)

-Peter
 
B

Bengt Richter

G. Völkl said:
Hello,

I use a dictionary:

phone = {'mike':10,'sue':8,'john':3}

phone['mike'] --> 10

I want to know who has number 3?
3 --> 'john'

Note that you can have many keys with the same value:
phone = {'mike':10,'sue':8,'john':3, 'jack': 3, 'helen' : 10}

How to get it in the python way ?

simplest way I could think of in 30':
def key_from_value(aDict, target):
return [key for key, value in aDict.items() if value==target]

key_from_value(phone, 3)
--> ['john', 'jack']

but this is a linear search, so not very efficient if phone is big.
Then you may want to maintain a reversed index:
(here again, simplest way I could think of)

def rev_index(aDict):
r = {}
for key, value in aDict.items():
if r.has_key(value):
r[value].append(key)
else:
r[value] = [key]
return r
rev_phone = rev_index(phone)
rev_phone
--> {8: ['sue'], 10: ['helen', 'mike'], 3: ['john', 'jack']}

{8: ['sue'], 10: ['helen', 'mike'], 3: ['john', 'jack']}

rev_phone[3]
--> ['john', 'jack']

But now you've got another problem : you need to update the reversed
index each time you modify the dictionary... Which would lead to writing
a class extending dict, maintaining a reversed index, and exposing extra
methods to handle this.
Not very tested:

----< twoway.py >--------------------
class Twoway(dict):
def __setitem__(self, name, number):
dict.__setitem__(self, name, number)
self.setdefault(number, []).append(name)
def __delitem__(self, name):
num = self[name]
dict.__delitem__(self, name)
self[num].remove(name)
if not self[num]: del self[num]
def __init__(self, src=None):
if src is None: return
dict.__init__(self, src)
for name, num in self.items(): self.setdefault(num, []).append(name)

if __name__ == '__main__':
phone = Twoway({'mike':10,'sue':8,'john':3, 'jack': 3, 'helen' : 10})
print 'jack:', phone['jack']
print 'same phone as jack:', phone[phone['jack']]
print 'deleting jack ...'; del phone['jack']
print 'john:', phone['john']
print phone
-------------------------------------

[13:05] C:\pywk\sovm>py24 twoway.py
jack: 3
same phone as jack: ['john', 'jack']
deleting jack ...
john: 3
{'mike': 10, 3: ['john'], 8: ['sue'], 10: ['mike', 'helen'], 'sue': 8, 'helen': 10, 'john': 3}

Regards,
Bengt Richter
 
J

Joal Heagney

Tim said:
G. Völkl said:
I use a dictionary:

phone = {'mike':10,'sue':8,'john':3}

phone['mike'] --> 10

I want to know who has number 3?

3 --> 'john'

How to get it in the python way ?


If you need to do this a lot, just keep two dictionaries, where the keys in
each are the values in the other.

reversephone = dict( zip( phone.values(), phone.keys() ) )

(Been away from python for a while, so forgive me if I'm asking a silly
question.)
Does python guarantee that the lists given by phone.values() and
phone.keys() are in mutual order? Or is it possible that python will
return the lists in different orders for .values() and .keys()?

Joal
 
B

Bengt Richter

Tim said:
G. Völkl said:
I use a dictionary:

phone = {'mike':10,'sue':8,'john':3}

phone['mike'] --> 10

I want to know who has number 3?

3 --> 'john'

How to get it in the python way ?


If you need to do this a lot, just keep two dictionaries, where the keys in
each are the values in the other.

reversephone = dict( zip( phone.values(), phone.keys() ) )

(Been away from python for a while, so forgive me if I'm asking a silly
question.)
Does python guarantee that the lists given by phone.values() and
phone.keys() are in mutual order? Or is it possible that python will
return the lists in different orders for .values() and .keys()?
Good question. I don't know. I hope so, but I would tend to write dict((v,k) for k,v in phone.items())
to do the equivalent, but note that it only works if everyone has a different phone number.
{3: 'sue', 4: 'bob'}

Surprised at who got left out? [('sue', 3), ('mike', 4), ('bob', 4)]

Regards,
Bengt Richter
 
P

Peter Otten

Joal said:
Does python guarantee that the lists given by phone.values() and
phone.keys() are in mutual order? Or is it possible that python will
return the lists in different orders for .values() and .keys()?

Yes. Quoted from http://docs.python.org/lib/typesmapping.html:

Keys and values are listed in an arbitrary order which is non-random, varies
across Python implementations, and depends on the dictionary's history of
insertions and deletions. If items(), keys(), values(), iteritems(),
iterkeys(), and itervalues() are called with no intervening modifications
to the dictionary, the lists will directly correspond. This allows the
creation of (value, key) pairs using zip(): "pairs = zip(a.values(),
a.keys())". The same relationship holds for the iterkeys() and itervalues()
methods: "pairs = zip(a.itervalues(), a.iterkeys())" provides the same
value for pairs. Another way to create the same list is "pairs = [(v, k)
for (k, v) in a.iteritems()]".

Peter
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,766
Messages
2,569,569
Members
45,042
Latest member
icassiem

Latest Threads

Top