Convert string to dictionary with list of values - python

What is the best way to convert a string to dictionary with value of dictionary as a list
for example
str = "abc=1,abc=2,abc=3,xyz=5,xyz=6"
i need the output as:
d = {"abc":["1","2","3"],"xyz":["5","6"]}
I'm very new to python.
my code:
d = {k: [v] for k, v in map(lambda item: item.split('='), s.split(","))}

Here is the solution with dict.setdefault method.
>>> help({}.setdefault)
Help on built-in function setdefault:
setdefault(key, default=None, /) method of builtins.dict instance
Insert key with a value of default if key is not in the dictionary.
Return the value for key if key is in the dictionary, else default.
>>> your_str = "abc=1,abc=2,abc=3,xyz=5,xyz=6"
>>>
>>> result = {}
>>>
>>> for pair in your_str.split(","):
... name, val = pair.split("=")
... result.setdefault(name, []).append(val)
>>> result
{'abc': ['1', '2', '3'], 'xyz': ['5', '6']}
You could also use defaultdict with default factory as list
>>> from collections import defaultdict
>>>
>>> your_str = "abc=1,abc=2,abc=3,xyz=5,xyz=6"
>>>
>>> result = defaultdict(list)
>>> for pair in str.split(","):
... name, val = pair.split("=")
... result[name].append(val)
...
>>> dict(result)
{'abc': ['1', '2', '3'], 'xyz': ['5', '6']}

The reason the code you have tried already isn't giving you the desired result is the fact that you are overwriting the value assigned to each key as you iterate over the list. What you need to do is append to the value already assigned to the key - except if the key doesn't exist, in which case you need to initialise that key.
This would be one way to go:
s1 = "abc=1,abc=2,abc=3,xyz=5,xyz=6"
list1 = [(each.split('=')) for each in s1.split(',')]
d = {}
for key, val in list1:
if key in d.keys():
d[key].append(val)
else:
d[key] = [val]
print (d)
#result: {'abc': ['1', '2', '3'], 'xyz': ['5', '6']}
You could simplify this and eliminate the if-else by using defaultdict, like so:
from collections import defaultdict
d = defaultdict(lambda: [])
s1 = "abc=1,abc=2,abc=3,xyz=5,xyz=6"
list1 = [(each.split('=')) for each in s1.split(',')]
for key, val in list1:
d[key].append(val)
print (d)
#result: {'abc': ['1', '2', '3'], 'xyz': ['5', '6']}

# initialize a dictionary
d = {}
# split the string (my_str) according to "," in order to get pairs such as 'abc/1' and 'xyz/5' in a list
for elt in my_str.split(",") :
# for each string of the list, split according to '/' to get the pairs ['abc', 1]
# complete the dictionary
if elt.split('/')[0] not in d.keys():
d[elt.split('/')[0]] = [elt.split('/')[1]]
else :
d[elt.split('/')[0]].append(elt.split('/')[1])

Related

Reduce nested dictionary to "top-key-root-element" dictionary

I would like to derive a dictionary from a nested dictionary with the top keys as keys and the root elements as values. This post is similar to this one, but I would like to end up with a dictionary not with a list of lists.
Example: How to get from this
d = {'foo':{'a':{'b':['1','2']}},
'bar':{'a':{'b':{'c':'3'}}}}
to this?
{'foo': ['1', '2'], 'bar': '3'}
d = {'foo':{'a':{'b':['1','2']}},
'bar':{'c':{'d':'3'}}}
def get_last_value(d):
if isinstance(d, dict):
for k, v in d.items():
return get_last_value(v)
return d
result = {k:get_last_value(v) for k, v in d.items()}
print(result)
result:
{'foo': ['1', '2'], 'bar': '3'}
d = {'foo':{'a':{'b':['1','2']}},
'bar':{'c':{'d':'3'}}}
for key, value, in d.items():
print(key, value.values())

How to add index to a list inside a dictionary

I have a dictionary here:
dict = {'A':['1','1','1','1','1'], 'B':['2','2'], 'C':['3','3','3','3']}
What is the necessary process to get the following result?
dict = {'A':['1_01','1_02','1_03','1_04','1_05'], 'B':['2_01','2_02'], 'C':['3_01','3_02','3_03','3_04']}
I have been learning python for quite a while now but dictionary is kind of new to me.
As others mentioned, refrain from using built-in keywords as variable names, such as dict. I kept it for simplicity on your part.
This is probably the most pythonic way of doing it (one line of code):
dict = {key:[x+"_0"+str(cnt+1) for cnt,x in enumerate(value)] for key,value in dict.items()}
You could also iterate through each dictionary item, and then each list item and manually change the list names as shown below:
for key,value in dict.items():
for cnt,x in enumerate(value):
dict[key][cnt] = x+"_0"+str(cnt+1)
Also, as some others have mentioned, if you want numbers greater than 10 to save as 1_10 rather than 1_010 you can you an if/else statement inside of the list comprehension...
dict = {key:[x+"_0"+str(cnt+1) if cnt+1 < 10 else x+"_"+str(cnt+1) for cnt,x in enumerate(value)] for key,value in dict.items()}
First iterate on keys.
Then loop on keys you are getting on key like for 'A' value is ['1','1','1','1','1'] then we can change the element at ['1','1','1','1','1']
enumerate() helps you iterate on index,value then index starts with zero as per your expected output add 1 to index. As you want the trailing 0 before each count we did '%02d'% (index+1)
Like this:
dict = {'A':['1','1','1','1','1'], 'B':['2','2'], 'C':['3','3','3','3']}
for i in dict.keys(): #iterate on keys
for index,val in enumerate(dict[i]): #took value as we have key in i
element='%02d'% (index+1) #add trailing 0 we converted 1 to int 01
dict[i][index]=val+"_"+ str(element) #assign new value with converting integer to string
print(dict)
Output:
{'A': ['1_01', '1_02', '1_03', '1_04', '1_05'], 'C': ['3_01', '3_02', '3_03', '3_04'], 'B': ['2_01', '2_02']}
Use enumerate to iterate over list keeping track of index:
d = {'A':['1','1','1','1','1'], 'B':['2','2'], 'C':['3','3','3','3']}
newd = {}
for k, v in d.items():
newd[k] = [f'{x}_0{i}' for i, x in enumerate(v, 1)]
print(newd)
Also a dictionary-comprehension:
d = {k: [f'{x}_0{i}' for i, x in enumerate(v, 1)] for k, v in d.items()}
Note: Don't name your dictionary as dict because it shadows the built-in.
d= {'A':['1','1','1','1','1'], 'B':['2','2'], 'C':['3','3','3','3']}
{x:[j + '_'+ '{:02}'.format(i+1) for i,j in enumerate(y)] for x,y in d.items()}
adict = {'A':['1','1','1','1','1'], 'B':['2','2'], 'C':['3','3','3','3'], 'D': '23454'}
newdict = {}
for i,v in adict.items():
if isinstance(v, list):
count = 0
for e in v:
count += 1
e += '_0' + str(count)
newdict[i] = newdict.get(i, [e]) + [e]
else:
newdict[i] = newdict.get(i, v)
print (newdict)
#{'A': ['1_01', '1_01', '1_02', '1_03', '1_04', '1_05'], 'B': ['2_01', '2_01', '2_02'], 'C': ['3_01', '3_01', '3_02', '3_03', '3_04'], 'D': '23454'}
This solution will check for whether your value in the dictionary is a list before assigning an index to it
You can use a dictcomp:
from itertools import starmap
d = {
'A': ['1', '1', '1', '1', '1'],
'B': ['2', '2'],
'C': ['3', '3', '3', '3']
}
f = lambda x, y: '%s_%02d' % (y, x)
print({k: list(starmap(f, enumerate(v, 1))) for k, v in d.items()})
# {'A': ['1_01', '1_02', '1_03', '1_04', '1_05'], 'B': ['2_01', '2_02'], 'C': ['3_01', '3_02', '3_03', '3_04']}

How to get a list which is a value of a dictionary by a value from the list?

I have the following dictionary :
d = {'1' : [1, 2, 3, 4], '2' : [10, 20, 30, 40]}
How do I get the corresponding key I'm searching by a value from one of the lists?
Let's say I want key '1' if I'm looking for value 3 or key '2' if I'm looking for value 10.
You can reverse the dictionary into this structure to do that kind of lookup:
reverse_d = {
1: '1',
2: '1',
3: '1',
4: '1',
10: '2',
…
}
which can be built by looping over each value of each key:
reverse_d = {}
for key, values in d.items():
for value in values:
reverse_d[value] = key
or more concisely as a dict comprehension:
reverse_d = {value: key for key, values in d.items() for value in values}
Lookups are straightforward now!
k = reverse_d[30]
# k = '2'
This only offers better performance than searching through the whole original dictionary if you do multiple lookups, though.
You can use a generator expression with a filtering condition, like this
>>> def get_key(d, search_value):
... return next(key for key, values in d.items() if search_value in values)
...
>>> get_key(d, 10)
'2'
>>> get_key(d, 2)
'1'
If none of the keys contain the value being searched for, None will be returned.
>>> get_key(d, 22)
None
This is my first time to answer question. How about this method?
def get_key(d,search_value):
res = []
for v in d.items():
if search_value in v[1]:
res.append(v[0])
return res
>>> D = {'a':[2,2,3,4,5],'b':[5,6,7,8,9]}
>>> getkey.get_key(D,2)
['a']
>>> getkey.get_key(D,9)
['b']
>>> getkey.get_key(D,5)
['a', 'b']

Selecting K largest values in a dictionary of dictionary in python

I have a dictionary of dictionary as below:
ls = [{'0': {'1': '1','2': '0.5','3': '1'},'1': {'0': '0.2','2': '1','3': '0.8'},}]
I would like to select k-largest values with their keys for each key of dictionary (ls). I have written below commands. It just gives me the k-largest keys without their values.
Python Code:
import heapq
k=2
for dic in ls:
for key in dic:
print(heapq.nlargest(k, dic[key], key=dic[key].get))
Output
['2', '3']
['3', '1']
I need to have value of each selected key.
First of all, I just wanted to check why you have
ls = [{'0': {'1': '1','2': '0.5','3': '1'},'1': {'0': '0.2','2': '1','3': '0.8'},}]
This is a list containing a dict, which doesn't match your description in the question.
Here is a solution that uses dict comprehensions that should give you what you want :)
def get_n_largest_vals(n, d):
x = {key: heapq.nlargest(len, map(int, d[key])) for key in d}
return {key: map(str, x[key]) for key in x}
Here it is being used for your problem:
ls = [{'0': {'1': '1','2': '0.5','3': '1'},'1': {'0': '0.2','2': '1','3': '0.8'},}]
d = ls[0]
get_n_largest_vals(2, d)
>>> {'0': ['3', '2'], '1': ['3', '2']}
How about:
from operator import itemgetter
for d in ls:
for key, d2 in d.items():
print(dict(heapq.nlargest(k, d2.items(), key=itemgetter(1))))
Notice that your values are still strings so they'd be lexically ordered, which is not what you want, because '2' > 12' And the dictionary is not ordered!

create dictionary from list same values

If i have a dictionary with lists with equal values:
a = {'abc': [['aaa', '123'], ['aaa, '321']]} how this values can be gathered to another dictionary like this: a = {'abc': {'aaa':['123','321']}}
I tried
aa = {'abc': [['aaa', '123'], ['aaa', '321']]}
ab = {}
bb = []
for i in aa:
for elem in aa[i]:
path = elem[0]
name = elem[1]
bb.append(name)
ab[path] = []
ab[path] = (bb)
print ab
But i don't think it's right way.
You can try like this:
def to_nested_dict(list_dict):
d = {} # initialize the outer dict
for k, lst in list_dict.items():
d[k] = {} # initialize inner dicts
for x, y in lst:
d[k].setdefault(x, []).append(y) # initialize and populate innermost list
return d
This uses setdefault to provide a defalt value (an empty list) in case of a new key, but you can just as well use an if-statement or a collections.defaultdict(list) for this.
Example:
>>> to_nested_dict({'abc': [['aaa', '123'], ['aaa', '321']]})
{'abc': {'aaa': ['123', '321']}}
>>> to_nested_dict({'abc': [['aaa', '123'], ['aaa', '321'], ['bbb', '456']]})
{'abc': {'aaa': ['123', '321'], 'bbb': ['456']}}
>>> to_nested_dict({'abc': [['aaa', '123'], ['aaa', '321'], ['bbb', '456']], 'efg': [['eee', '789']]})
{'abc': {'aaa': ['123', '321'], 'bbb': ['456']}, 'efg': {'eee': ['789']}}
Not that this assumes that the inner-most lists will always have two elements, a key and a value, and that the key can be the same in different lists, but can also differ, resulting in more than one entry in the created dictionaries.
Here is a one line solution for you:
ab = { k:{v[0][0]:[ x[1] for x in v ] } for k,v in aa.iteritems() }
Output:
print ab
{'abc': {'aaa': ['123', '321']}}
Voilà

Categories