I have dictionary structure. For example:
dict = {key1 : value1 ,key2 : value2}
What I want is the string which combines the key and the value
Needed string -->> key1_value1 , key2_value2
Any Pythonic way to get this will help.
Thanks
def checkCommonNodes( id , rs):
for r in rs:
for key , value in r.iteritems():
kv = key+"_"+value
if kv == id:
print "".join('{}_{}'.format(k,v) for k,v in r.iteritems())
A list of key-value strs,
>>> d = {'key1': 'value1', 'key2': 'value2'}
>>> ['{}_{}'.format(k,v) for k,v in d.iteritems()]
['key2_value2', 'key1_value1']
Or if you want a single string of all key-value pairs,
>>> ', '.join(['{}_{}'.format(k,v) for k,v in d.iteritems()])
'key2_value2, key1_value1'
EDIT:
Maybe you are looking for something like this,
def checkCommonNodes(id, rs):
id_key, id_value = id.split('_')
for r in rs:
try:
if r[id_key] == id_value:
print "".join('{}_{}'.format(k,v) for k,v in r.iteritems())
except KeyError:
continue
You may also be wanting to break after printing - hard to know exactly what this is for.
Assuming Python 2.x, I would use something like this
dict = {'key1': 'value1', 'key2': 'value2'}
str = ''.join(['%s_%s' % (k,v) for k,v in dict.iteritems()])
def checkCommonNodes(id, rs):
k,v = id.split('_')
for d in rs:
if d.get(k) == v:
return id
retun None
Updated answer for Python 3.x
Example one - join a single key, value in the form "key_value"
k = 'key1'
v = 'value1'
mystring = f'{k}={v}'
print(mystring)
# result -> key1=value1
Example two: create a list of all key-value pairs as strings in the form "key_value"
mydict = {'key1': 'value1', 'key2': 'value2'}
mylist = [f'{k}_{v}' for k,v in mydict.items()]
print(mylist)
# result -> ['key1_value1', 'key2_value2']
Example three: transform a list to a string
result = ', '.join(mylist)
print(result)
# result -> key1_value1, key2_value2
Putting it all together - join all key-value pairs in a dictionary and output as a string.
mydict = {'key1': 'value1', 'key2': 'value2'}
result = ', '.join([f'{k}_{v}' for k,v in mydict.items()])
print(result)
# result -> key1_value1, key2_value2
This is the same basic answer provided by Jared, but now with Python 3.x we use the .items() function instead of .iteritems(), and we can use an f-string instead of the string format() function (although the latter does still work too).
This may not be exactly the perfect answer to the original question asked 12+ years ago (!) but it is a more generic answer about transforming dictionary key-value pairs to (key + value), as indicated by the question title.
Related
I am trying to create a function that takes in a dictionary and returns a reverse of it while taking care of repeated values. That is, if the original dictionary would be
original_dict = {'first': ['a'], 'second': ['b', 'c'], 'third': ['d'], 'fourth': ['d']}
the function should return
{'a': ['first'], 'b': ['second'], 'c': ['second'], 'd': ['third', 'fourth']}
I've written
def reversed_dict(d):
new_dict = {}
for keys,values in d.items():
new_dict[values]=keys
but when I try it out with the original dictionary, I get an error "unhashable type: 'list'" when I try out the function. Are there any hints what might be causing it?
You have to iterate over the values in the list as well:
def reversed_dict(d):
new_dict = {}
for keys,values in d.items():
for val in values:
new_dict.setdefault(val, []).append(keys)
return new_dict
You have to iterate over the values and add them as keys. You also have to take into account the possibility that you may have already added a value as a key.
def reversed_dict(d):
new_dict = {}
for keys,values in d.items():
for v in values:
if v in new_dict:
new_dict[v].append(keys)
else:
new_dict[v] = [keys]
return new_dict
Use collections.defaultdict:
from collections import defaultdict
def reversed_dict(d):
new_dict = defaultdict(list)
for key, values in d.items():
for value in values:
new_dict[value].append(key)
return new_dict
The problem with your approach is you're using the entire list as the key of the dictionary. Instead you need to iterate over the list (i.e. for value in values: in the code above.)
defaultdict just makes it simpler to read.
You are getting this error because any of your original_dict values is a mutable type which is, as the error suggests, an unhashable type thus not
avalid candidate for a key in the reversed_dict.
You can workaround this problem by type-checking and casting mutable types into an immutable equivalent, e.g. a list into a tuple.
(also I find dict comp a way more elegant and concise approach):
def reversed_dict(d):
return {v if not isinstance(v, list) else tuple(v): k for k, v in d.items()}
I have two dictionaries. In both dictionaries, the value of each key is a single list. If any element in any list in dictionary 2 is equal to a key of dictionary 1, I want to replace that element with the first element in that dictionary 1 list.
In other words, I have:
dict1 = {'IDa':['newA', 'x'], 'IDb':['newB', 'x']}
dict2 = {1:['IDa', 'IDb']}
and I want:
dict2 = {1:['newA', 'newB']}
I tried:
for ID1, news in dict1.items():
for x, ID2s in dict2.items():
for ID in ID2s:
if ID == ID1:
print ID1, 'match'
ID.replace(ID, news[0])
for k, v in dict2.items():
print k, v
and I got:
IDb match
IDa match
1 ['IDa', IDb']
So it looks like everything up to the replace method is working. Is there a way to make this work? To replace an entire string in a value-list with a string in another value-list?
Thanks a lot for your help.
Try this:
dict1 = {'IDa':['newA', 'x'], 'IDb':['newB', 'x']}
dict2 = {1:['IDa', 'IDb']}
for key in dict2.keys():
dict2[key] = [dict1[x][0] if x in dict1.keys() else x for x in dict2[key]]
print dict2
this will print:
{1: ['newA', 'newB']}
as required.
Explanation
dict.keys() gives us just the keys of a dictionary (i.e. just the left hand side of the colon). When we use for key in dict2.keys(), at present our only key is 1. If the dictionary was larger, it'd loop through all keys.
The following line uses a list comprehension - we know that dict2[key] gives us a list (the right side of the colon), so we loop through every element of the list (for x in dict2[key]) and return the first entry of the corresponding list in dict1 only if we can find the element in the keys of dict1 (dict1[x][0] if x in dict1.keys) and otherwise leave the element untouched ([else x]).
For example, if we changed our dictionaries to be the following:
dict1 = {'IDa':['newA', 'x'], 'IDb':['newB', 'x']}
dict2 = {1:['IDa', 'IDb'], 2:{'IDb', 'IDc'}}
we'd get the output:
{1: ['newA', 'newB'], 2: ['newB', 'IDc']}
because 'IDc' doesn't exist in the keys of dict1.
You could also use dictionary comprehensions, but I am not sure that they are working in Python 2.7, it may be limited to Python 3 :
# Python 3
dict2 = {k: [dict1.get(e, [e])[0] for e in v] for k,v in dict2.items()}
edit: I just checked, this is working in Python 2.7. However, dict2.items() should be replaced by dict2.iteritems() :
# Python 2.7
dict2 = {k: [dict1.get(e, [e])[0] for e in v] for k,v in dict2.iteritems()}
This was a fun one!
dict2[1] = [dict1[val][0] if val in dict1 else val for val in dict2[1]]
Or, here is the same logic without list comprehension:
new_dict = {1: []}
for val in dict2[1]:
if val in dict1:
new_dict[1].append(dict1[val][0])
else:
new_dict[1].append(val)
dict2 = new_dict
I have a dictionary with 20 000 plus entries with at the moment simply the unique word and the number of times the word was used in the source text (Dante's Divine Comedy in Italian).
I would like to work through all entries replacing the value with an actual definition as I find them. Is there a simple way to iterate through the keywords that have as a value a number in order to replace (as I research the meaning)?
The dictionary starts:
{'corse': 378, 'cielo,': 209, 'mute;': 16, 'torre,': 11, 'corsa': 53, 'assessin': 21, 'corso': 417, 'Tolomea': 21} # etc.
Sort of an application that will suggest a keyword to research and define.
via dict.update() function
In case you need a declarative solution, you can use dict.update() to change values in a dict.
Either like this:
my_dict.update({'key1': 'value1', 'key2': 'value2'})
or like this:
my_dict.update(key1='value1', key2='value2')
via dictionary unpacking
Since Python 3.5 you can also use dictionary unpacking for this:
my_dict = { **my_dict, 'key1': 'value1', 'key2': 'value2'}
Note: This creates a new dictionary.
via merge operator or update operator
Since Python 3.9 you can also use the merge operator on dictionaries:
my_dict = my_dict | {'key1': 'value1', 'key2': 'value2'}
Note: This creates a new dictionary.
Or you can use the update operator:
my_dict |= {'key1': 'value1', 'key2': 'value2'}
You cannot select on specific values (or types of values). You'd either make a reverse index (map numbers back to (lists of) keys) or you have to loop through all values every time.
If you are processing numbers in arbitrary order anyway, you may as well loop through all items:
for key, value in inputdict.items():
# do something with value
inputdict[key] = newvalue
otherwise I'd go with the reverse index:
from collections import defaultdict
reverse = defaultdict(list)
for key, value in inputdict.items():
reverse[value].append(key)
Now you can look up keys by value:
for key in reverse[value]:
inputdict[key] = newvalue
If you iterate over a dictionary you get the keys, so assuming your dictionary is in a variable called data and you have some function find_definition() which gets the definition, you can do something like the following:
for word in data:
data[word] = find_definition(word)
I think this may help you solve your issue.
Imagine you have a dictionary like this:
dic0 = {0:"CL1", 1:"CL2", 2:"CL3"}
And you want to change values by this one:
dic0to1 = {"CL1":"Unknown1", "CL2":"Unknown2", "CL3":"Unknown3"}
You can use code bellow to change values of dic0 properly respected to dic0to1 without worrying yourself about indexes in dictionary:
for x, y in dic0.items():
dic0[x] = dic0to1[y]
Now you have:
>>> dic0
{0: 'Unknown1', 1: 'Unknown2', 2: 'Unknown3'}
Just had to do something similar. My approach for sanitizing data for python based on Sadra Sabouri's answer:
def sanitize(value):
if str(value) == 'false':
return False
elif str(value) == 'true':
return True
elif str(value) == 'null':
return None
return value
for k,v in some_dict.items():
some_dict[k] = sanitize(v)
data = {key1: value1, key2: value2, key3: value3}
for key in data:
if key == key1:
data[key1] = change
print(data)
this will replace key1: value1 to key1: change
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Inverse dictionary lookup - Python
Is there a built in way to index a dictionary by value in Python.
e.g. something like:
dict = {'fruit':'apple','colour':'blue','meat':'beef'}
print key where dict[key] == 'apple'
or:
dict = {'fruit':['apple', 'banana'], 'colour':'blue'}
print key where 'apple' in dict[key]
or do I have to manually loop it?
You could use a list comprehension:
my_dict = {'fruit':'apple','colour':'blue','meat':'beef'}
print [key for key, value in my_dict.items() if value == 'apple']
The code above is doing almost exactly what said you want:
print key where dict[key] == 'apple'
The list comprehension is going through all the key, value pairs given by your dictionary's items method, and making a new list of all the keys where the value is 'apple'.
As Niklas pointed out, this does not work when your values could potentially be lists. You have to be careful about just using in in this case since 'apple' in 'pineapple' == True. So, sticking with a list comprehension approach requires some type checking. So, you could use a helper function like:
def equals_or_in(target, value):
"""Returns True if the target string equals the value string or,
is in the value (if the value is not a string).
"""
if isinstance(target, str):
return target == value
else:
return target in value
Then, the list comprehension below would work:
my_dict = {'fruit':['apple', 'banana'], 'colour':'blue'}
print [key for key, value in my_dict.items() if equals_or_in('apple', value)]
You'll have to manually loop it, but if you'll need the lookup repeatedly this is a handy trick:
d1 = {'fruit':'apple','colour':'blue','meat':'beef'}
d1_rev = dict((v, k) for k, v in d1.items())
You can then use the reverse dictionary like this:
>>> d1_rev['blue']
'colour'
>>> d1_rev['beef']
'meat'
Your requirements are more complex than you realize:
You need to handle both list values and plain values
You don't actually need to get back a key, but a list of keys
You could solve this in two steps:
normalize the dict so that every value is a list (every plain value becomes a single-element)
build a reverse dictionary
The following functions will solve this:
from collections import defaultdict
def normalize(d):
return { k:(v if isinstance(v, list) else [v]) for k,v in d.items() }
def build_reverse_dict(d):
res = defaultdict(list)
for k,values in normalize(d).items():
for x in values:
res[x].append(k)
return dict(res)
To be used like this:
>>> build_reverse_dict({'fruit':'apple','colour':'blue','meat':'beef'})
{'blue': ['colour'], 'apple': ['fruit'], 'beef': ['meat']}
>>> build_reverse_dict({'fruit':['apple', 'banana'], 'colour':'blue'})
{'blue': ['colour'], 'apple': ['fruit'], 'banana': ['fruit']}
>>> build_reverse_dict({'a':'duplicate', 'b':['duplicate']})
{'duplicate': ['a', 'b']}
So you just build up the reverse dictionary once and then lookup by value and get back a list of keys.
I have many dictionaries like this:
dict1 = {1:[1,2,3],2:[2,3,4]}
dict2 = {2:[3,4,5],3:[4,5,6]}
I need to get
dict = {1:[1,2,3],2:[2,3,4,3,4,5],3:[4,5,6]}
# ^
# | order is unimportant
What is the best way of doing it?
Simple iteration an extending list...
for key, value in dict2.iteritems():
dict1.setdefault(key, []).extend(value)
Iterate through the keys of dict2; if the same key exists in dict1, concatenate the lists and set in dict1; otherwise just set in dict1
dict1 = {1:[1,2,3],2:[2,3,4]}
dict2 = {2:[3,4,5],3:[4,5,6]}
dicts = [dict1, dict2]
new_dict = {}
for d in dicts:
for k, v in d.iteritems():
if new_dict.has_key(k):
new_dict[k] = new_dict[k] + v
else:
new_dict[k] = v
a = {'a' : [1,2], 'b' : [3,4]}
b = {'a' : [3,4], 'b' : [1,2]}
for key in a.keys():
for elem in a[key]:
b[key].append(elem)
Oh, maybe there's some clever way to do it with reduce, but why not just write code like a normal person.
dict = {}
for each_dict in (dict1, dict2, ...): # ... is not real code
for key, value in each_dict:
if not dict.has_key(key):
dict[key] = []
dict[key] += value # list append operator
I have many dictionaries like this:
This way lets you "glue together" multiple dictionaries at a time:
dict(
(k, sum((d.get(k, []) for d in dicts), []))
for k in set(sum((d.keys() for d in dicts), []))
)