Tuple from dict of dict in Python - python

i've a dict of dict in python, for getting a random value from the dict
words = {0:{"wake up": "aaaa"},
1:{"look after": "bbbb"},
2:{"turn on": "cccc"}
}
i want extract the second dict (the values of a number key) from the dict words
(k, v) = words[random.randint(0, 22)]
but the error is thisone
ValueError: need more than 1 value to unpack
why i need another values?

You are accessing the dictionary with a key, which returns just the value:
value = words[random.randint(0, 22)]
but if your keys are all integers, you would be better off using a list instead:
words = [{"wake up": "aaaa"}, {"look after": "bbbb"}, {"turn on": "cccc"}]
value = random.choice(words)
and let random.choice() do all the hard work of picking one at random.
You can still use random.choice() with dictionary values too of course:
value = random.choice(list(words.values()))
would return a random value from the dictionary, and:
key, value = random.choice(list(words.items()))
would return a random (key, value) pair for you.
If you meant to extract the stored dictionary into a key and value, you'd have to extract just one key-value pair from that object; you cannot use tuple unpacking on a dictionary:
>>> key, value = {'foo': 'bar'}
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ValueError: need more than 1 value to unpack
but this works:
>>> key, value = next(iter({'foo': 'bar'}.items()))
>>> key, value
('foo', 'bar')
but perhaps you should be storing tuples instead of dictionaries if you wanted to extract a random key-value pair, or store the keys and values directly in the words dictionary.

Summary: Method 3 is the most pythonic way to do it.
Without any modification to the data structures, the following code will work for you:
k, v = words[random.randint(0, 2)].items()[0]
However, this is not the best (& pythonic) way to do it.
If your inner dict always has a single key-value pair, then there is really no need to keep it as a dict. Rather, keep the inner data as a tuple.
words = {0: ("wake up", "aaaa"),
1:("look after", "bbbb"),
2:("turn on", "cccc")
}
# Now, the following line should work fine
k, v = words[random.randint(0, 2)]
And If there is no restriction on the outer data structure either, then use list or tuple as follows:
words = (
("wake up", "aaaa"),
("look after", "bbbb"),
("turn on", "cccc")
)
# Now, the random.choice can be used
k, v = random.choice(words)

Related

Dict comprehension, tuples and lazy evaluation

I am trying to see if I can pull off something quite lazy in Python.
I have a dict comprehension, where the value is a tuple. I want to be able to create the second entry of the tuple by using the first entry of the tuple.
An example should help.
dictA = {'a': 1, 'b': 3, 'c': 42}
{key: (a = someComplexFunction(value), moreComplexFunction(a)) for key, value in dictA.items()}
Is it possible that the moreComplexFunction uses the calculation in the first entry of the tuple?
You could add a second loop over a one-element tuple:
{key: (a, moreComplexFuntion(a)) for key, value in dictA.items()
for a in (someComplexFunction(value),)}
This gives you access to the output of someComplexFunction(value) in the value expression, but that's rather ugly.
Personally, I'd move to a regular loop in such cases:
dictB = {}
for key, value in dictA.items():
a = someComplexFunction(value)
dictB[key] = (a, moreComplexFunction(a))
and be done with it.
or, you could just write a function to return the tuple:
def kv_tuple(a):
tmp = someComplexFunction(a)
return (a, moreComplexFunction(tmp))
{key:kv_tuple(value) for key, value in dictA.items()}
this also gives you the option to use things like namedtuple to get names for the tuple items, etc. I don't know how much faster/slower this would be though... the regular loop is likely to be faster (fewer function calls)...
Alongside Martijn's answer, using a generator expression and a dict comprehension is also quite semantic and lazy:
dictA = { ... } # Your original dict
partially_computed = ((key, someComplexFunction(value))
for key, value in dictA.items())
dictB = {key: (a, moreComplexFunction(a)) for key, a in partially_computed}

How to construct nested dictionary comprehension in Python with correct ordering?

I was trying to shorten the code for this problem when I encountered the problem.
Basically, I was trying a nested dictionary comprehension & was unsuccessful in the attempt.
Here is what I tried.
dict2 = {key:value for key, value in line.split(":")
for line in ["1:One", "2:Two", "4:Four"]}
print dict2
When I run this, it gives me
NameError: name 'line' is not defined
And, when I reverse the for statements like this
dict2 = {key:value for line in ["1:One", "2:Two", "4:Four"]
for key, value in line.split(":")}
print dict2
It results in
ValueError: need more than 1 value to unpack
I need help on the nesting structure of dictionary (or list) comprehension. An example would be help a lot.
Note that there is a better way of doing this without a dict comprehension; see below. I’ll first address the issues with your approach.
You need to use nesting order in comprehensions. List your loops in the same order they would be in when nesting a regular loop.
The line.split() expression returns a sequence of two items, but each of those items is not a tuple of a key and a value; instead there is only ever one element being iterated over. Wrap the split in a tuple so you have a 'sequence' of (key, value) items being yielded to assign the two results to two items:
dict2 = {key:value for line in ["1:One", "2:Two", "4:Four"]
for key, value in (line.split(":"),)}
This is the equivalent of:
dict2 = {}
for line in ["1:One", "2:Two", "4:Four"]:
for key, value in (line.split(":"),):
dict2[key] = value
where the nested loop is only needed because you cannot do:
dict2 = {}
for line in ["1:One", "2:Two", "4:Four"]:
key, value = line.split(":")
dict2[key] = value
However, in this case, instead of a dictionary comprehension, you should use the dict() constructor. It wants two-element sequences, simplifying the whole operation:
dict2 = dict(line.split(":") for line in ["1:One", "2:Two", "4:Four"])
You can do this a lot simpler with dict and a generator expression:
>>> lst = ["1:One", "2:Two", "4:Four"]
>>> dict(x.split(":") for x in lst)
{'4': 'Four', '1': 'One', '2': 'Two'}
>>>

How can you print a key given a value in a dictionary for Python?

For example lets say we have the following dictionary:
dictionary = {'A':4,
'B':6,
'C':-2,
'D':-8}
How can you print a certain key given its value?
print(dictionary.get('A')) #This will print 4
How can you do it backwards? i.e. instead of getting a value by referencing the key, getting a key by referencing the value.
I don't believe there is a way to do it. It's not how a dictionary is intended to be used...
Instead, you'll have to do something similar to this.
for key, value in dictionary.items():
if 4 == value:
print key
In Python 3:
# A simple dictionary
x = {'X':"yes", 'Y':"no", 'Z':"ok"}
# To print a specific key (for instance the 2nd key which is at position 1)
print([key for key in x.keys()][1])
Output:
Y
The dictionary is organized by: key -> value
If you try to go: value -> key
Then you have a few problems; duplicates, and also sometimes a dictionary holds large (or unhashable) objects which you would not want to have as a key.
However, if you still want to do this, you can do so easily by iterating over the dicts keys and values and matching them as follows:
def method(dict, value):
for k, v in dict.iteritems():
if v == value:
yield k
# this is an iterator, example:
>>> d = {'a':1, 'b':2}
>>> for r in method(d, 2):
print r
b
As noted in a comment, the whole thing can be written as a generator expression:
def method(dict, value):
return (k for k,v in dict.iteritems() if v == value)
Python versions note: in Python 3+ you can use dict.items() instead of dict.iteritems()
target_key = 4
for i in dictionary:
if dictionary[i]==target_key:
print(i)
Within a dictionary if you have to find the KEY for the highest VALUE please do the following :
Step 1: Extract all the VALUES into a list and find the Max of list
Step 2: Find the KEY for the particular VALUE from Step 1
The visual analyzer of this code is available in this link : LINK
dictionary = {'A':4,
'B':6,
'C':-2,
'D':-8}
lis=dictionary.values()
print(max(lis))
for key,val in dictionary.items() :
if val == max(lis) :
print("The highest KEY in the dictionary is ",key)
I think this is way easier if you use the position of that value within the dictionary.
dictionary = {'A':4,
'B':6,
'C':-2,
'D':-8}
# list out keys and values separately
key_list = list(dictionary.keys())
val_list = list(dictionary.values())
# print key with val 4
position = val_list.index(4)
print(key_list[position])
# print key with val 6
position = val_list.index(6)
print(key_list[position])
# one-liner
print(list(my_dict.keys())[list(my_dict.values()).index(6)])
Hey i was stuck on a thing with this for ages, all you have to do is swap the key with the value e.g.
Dictionary = {'Bob':14}
you would change it to
Dictionary ={1:'Bob'}
or vice versa to set the key as the value and the value as the key so you can get the thing you want

Defining a list of values for a dictionary key using an external file

I have a file with a list of paired entries (keys) that goes like this:
6416 2318
84665 88
90 2339
2624 5371
6118 6774
And I've got another file with the values to those keys:
266743 Q8IUM7
64343 H7BXU6
64343 Q9H6S1
64343 C9JB40
23301 Q8NDI1
23301 A8K930
As you can see the same key can have more than one value. What I'm trying to do is creating a dictionary by automatically creating the initial k, v pair, and then append more values for each entry that is already in the dictionary, like this:
Program finds "266743: 'Q8IUM7'", then "64343: 'H7BXU6'". And when it finds "64343: 'Q9H6S1'" it does this: "64343: ['H7BXU6', 'Q9H6S1']".
This is what I have so far:
# Create dictionary
data = {}
for line in inmap:
value = []
k, v = [x.strip() for x in line.split('\t')]
data[k] = value.append(v)
if k in data.viewkeys() == True and v in data.viewvalues() == False:
data[k] = value.append(v)
But the if statement seems to not be working. That or having the value = [] inside the for loop. Any thoughts?
This is not a good idea. You should be using a list from the start and expand that list as you go along, not change from "string" to "list of strings" when more than one value is found for the key.
For this, you can simply use
from collections import defaultdict
data = defaultdict(list)
for line in inmap:
k, v = (x.strip() for x in line.split('\t'))
data[k].append(v)
This works because a defaultdict of type list will automatically create a key together with an empty list as its value when you try to reference a key that doesn't yet exist. Otherwise, it behaves just like a normal dictionary.
Result:
>>> data
defaultdict(<type 'list'>, {'23301': ['Q8NDI1', 'A8K930'],
'64343': ['H7BXU6', 'Q9H6S1', 'C9JB40'], '266743': ['Q8IUM7']})

How to print a dictionary's key?

I would like to print a specific Python dictionary key:
mydic = {}
mydic['key_name'] = 'value_name'
Now I can check if mydic.has_key('key_name'), but what I would like to do is print the name of the key 'key_name'. Of course I could use mydic.items(), but I don't want all the keys listed, merely one specific key. For instance I'd expect something like this (in pseudo-code):
print "the key name is", mydic['key_name'].name_the_key(), "and its value is", mydic['key_name']
Is there any name_the_key() method to print a key name?
Edit:
OK, thanks a lot guys for your reactions! :) I realise my question is not well formulated and trivial. I just got confused because I realised 'key_name' and mydic['key_name'] are two different things and I thought it would be incorrect to print the 'key_name' out of the dictionary context. But indeed I can simply use the 'key_name' to refer to the key! :)
A dictionary has, by definition, an arbitrary number of keys. There is no "the key". You have the keys() method, which gives you a python list of all the keys, and you have the iteritems() method, which returns key-value pairs, so
for key, value in mydic.iteritems() :
print key, value
Python 3 version:
for key, value in mydic.items() :
print (key, value)
So you have a handle on the keys, but they only really mean sense if coupled to a value. I hope I have understood your question.
Additionally you can use....
print(dictionary.items()) #prints keys and values
print(dictionary.keys()) #prints keys
print(dictionary.values()) #prints values
Hmm, I think that what you might be wanting to do is print all the keys in the dictionary and their respective values?
If so you want the following:
for key in mydic:
print "the key name is" + key + "and its value is" + mydic[key]
Make sure you use +'s instead of ,' as well. The comma will put each of those items on a separate line I think, where as plus will put them on the same line.
dic = {"key 1":"value 1","key b":"value b"}
#print the keys:
for key in dic:
print key
#print the values:
for value in dic.itervalues():
print value
#print key and values
for key, value in dic.iteritems():
print key, value
Note:In Python 3, dic.iteritems() was renamed as dic.items()
The name of the key 'key_name' is 'key_name', therefore
print('key_name')
or whatever variable you have representing it.
In Python 3:
# A simple dictionary
x = {'X':"yes", 'Y':"no", 'Z':"ok"}
# To print a specific key (for example key at index 1)
print([key for key in x.keys()][1])
# To print a specific value (for example value at index 1)
print([value for value in x.values()][1])
# To print a pair of a key with its value (for example pair at index 2)
print(([key for key in x.keys()][2], [value for value in x.values()][2]))
# To print a key and a different value (for example key at index 0 and value at index 1)
print(([key for key in x.keys()][0], [value for value in x.values()][1]))
# To print all keys and values concatenated together
print(''.join(str(key) + '' + str(value) for key, value in x.items()))
# To print all keys and values separated by commas
print(', '.join(str(key) + ', ' + str(value) for key, value in x.items()))
# To print all pairs of (key, value) one at a time
for e in range(len(x)):
print(([key for key in x.keys()][e], [value for value in x.values()][e]))
# To print all pairs (key, value) in a tuple
print(tuple(([key for key in x.keys()][i], [value for value in x.values()][i]) for i in range(len(x))))
Since we're all trying to guess what "print a key name" might mean, I'll take a stab at it. Perhaps you want a function that takes a value from the dictionary and finds the corresponding key? A reverse lookup?
def key_for_value(d, value):
"""Return a key in `d` having a value of `value`."""
for k, v in d.iteritems():
if v == value:
return k
Note that many keys could have the same value, so this function will return some key having the value, perhaps not the one you intended.
If you need to do this frequently, it would make sense to construct the reverse dictionary:
d_rev = dict(v,k for k,v in d.iteritems())
Update for Python3: d.iteritems() is not longer supported in Python 3+ and should be replaced by d.items()
d_rev = {v: k for k, v in d.items()}
# highlighting how to use a named variable within a string:
mapping = {'a': 1, 'b': 2}
# simple method:
print(f'a: {mapping["a"]}')
print(f'b: {mapping["b"]}')
# programmatic method:
for key, value in mapping.items():
print(f'{key}: {value}')
# yields:
# a 1
# b 2
# using list comprehension
print('\n'.join(f'{key}: {value}' for key, value in dict.items()))
# yields:
# a: 1
# b: 2
Edit: Updated for python 3's f-strings...
Make sure to do
dictionary.keys()
rather than
dictionary.keys
import pprint
pprint.pprint(mydic.keys())
Or you can do it that manner:
for key in my_dict:
print key, my_dict[key]
dict = {'name' : 'Fred', 'age' : 100, 'employed' : True }
# Choose key to print (could be a user input)
x = 'name'
if x in dict.keys():
print(x)
What's wrong with using 'key_name' instead, even if it is a variable?
Probably the quickest way to retrieve only the key name:
mydic = {}
mydic['key_name'] = 'value_name'
print mydic.items()[0][0]
Result:
key_name
Converts the dictionary into a list then it lists the first element which is the whole dict then it lists the first value of that element which is: key_name
I'm adding this answer as one of the other answers here (https://stackoverflow.com/a/5905752/1904943) is dated (Python 2; iteritems), and the code presented -- if updated for Python 3 per the suggested workaround in a comment to that answer -- silently fails to return all relevant data.
Background
I have some metabolic data, represented in a graph (nodes, edges, ...). In a dictionary representation of those data, keys are of the form (604, 1037, 0) (representing source and target nodes, and the edge type), with values of the form 5.3.1.9 (representing EC enzyme codes).
Find keys for given values
The following code correctly finds my keys, given values:
def k4v_edited(my_dict, value):
values_list = []
for k, v in my_dict.items():
if v == value:
values_list.append(k)
return values_list
print(k4v_edited(edge_attributes, '5.3.1.9'))
## [(604, 1037, 0), (604, 3936, 0), (1037, 3936, 0)]
whereas this code returns only the first (of possibly several matching) keys:
def k4v(my_dict, value):
for k, v in my_dict.items():
if v == value:
return k
print(k4v(edge_attributes, '5.3.1.9'))
## (604, 1037, 0)
The latter code, naively updated replacing iteritems with items, fails to return (604, 3936, 0), (1037, 3936, 0.
I looked up this question, because I wanted to know how to retrieve the name of "the key" if my dictionary only had one entry. In my case, the key was unknown to me and could be any number of things. Here is what I came up with:
dict1 = {'random_word': [1,2,3]}
key_name = str([key for key in dict1]).strip("'[]'")
print(key_name) # equal to 'random_word', type: string.
Try this:
def name_the_key(dict, key):
return key, dict[key]
mydict = {'key1':1, 'key2':2, 'key3':3}
key_name, value = name_the_key(mydict, 'key2')
print 'KEY NAME: %s' % key_name
print 'KEY VALUE: %s' % value
key_name = '...'
print "the key name is %s and its value is %s"%(key_name, mydic[key_name])
If you want to get the key of a single value, the following would help:
def get_key(b): # the value is passed to the function
for k, v in mydic.items():
if v.lower() == b.lower():
return k
In pythonic way:
c = next((x for x, y in mydic.items() if y.lower() == b.lower()), \
"Enter a valid 'Value'")
print(c)

Categories