create dictionary from list same values - python

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Ă 

Related

Convert string to dictionary with list of values

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

Python - Return the dictionary key comparing dictionary values with list

I was trying to compare a list with dictionary values to see if they match so I could return the key, but I couldn't find a solution to match them:
>>> my_dict = {'A': ['apple', 'america'], B: ['bee', 'bar'], C: ['car','cake','cat'], D: ['dad']}
>>> my_list = ['apple', 'dad']
In this case, the result would be:
['A', 'D']
What would be the best approach? I tried a nested for-loop, but I was wondering if there is a more direct answer.
my_second_dict = {}
for key in my_dict.keys():
for values in my_dict[key]:
I am not really sure how to do it. I'd appreciate your help.
Thanks!
You have a list of values and you want the keys of the dictionary items that have those values in their values (which are lists of values). This is assuming there are no duplicates in the lists in the dictionary (which seems reasonable, since it appears to group them by initial).
This is a solution:
my_dict = {'A': ['apple', 'america'], 'B': ['bee', 'bar'], 'C': ['car','cake','cat'], 'D': ['dad']}
my_list = ['apple', 'dad']
my_result = [k for v in my_list for k, vs in my_dict.items() if v in vs]
print(my_result)
Result:
['A', 'D']
Do you mean something like this?
my_dict = {'A': ['apple', 'america'], B: ['bee', 'bar'], C: ['car','cake','cat'], D: ['dad']}
my_list = ['apple', 'dad']
results = []
for key in my_dict.keys():
for value in my_list:
if value in my_dict[key]:
results.append(key)
break
print(results)
Loop through the keys in the dictionary, and check if any of the values in the list are in the dictionary.
You do not need to use the break statement if you use set intersection or list comprehension.
my_dict = {'A': ['apple', 'america'], B: ['bee', 'bar'], C: ['car','cake','cat'], D: ['dad']}
my_list = ['apple', 'dad']
results = []
for key in my_dict.keys():
if set(my_list).intersection(set(dict[key])):
results.append(key)
print(results)
my_dict = {'A': ['apple', 'america'], B: ['bee', 'bar'], C: ['car','cake','cat'], D: ['dad']}
my_list = ['apple', 'dad']
results = []
for key in my_dict.keys():
if any([val in my_dict[key] for val in my_list]):
results.append(key)
print(results)
I think if you finish your loop, you can end up with something like this:
output = []
for i in my_list:
for k, v in my_dict.items():
if i in v:
output.append(k)
or a one-liner
output = [k for i in my_list for k, v in my_dict.items() if i in v]

How to convert a flat list into a dictionary in python?

I have a flat list containing information of multiple variables and need to convert it into a dictionary. For example, 'a','b','c' are variable names and need to be the keys in the dictionary. The list could be split by '_' and ':'.
list_x = ['a:1_b:45_c:abc','a:2_b:24_c:def','a:4_b:78_c:xxx']
The desired output would be:
dict_x = {'a':[1,2,4],'b':[45,24,78],'c':['abc','def','xxx']}
I am not sure how to loop to get the keys for the dictionary since it is the same for all elements in the list.
lst = [y.split(":") for x in [x.split("_") for x in list_x] for y in x]
d = {x:[] for x in set([x[0] for x in lst])}
for k, v in lst:
d[k].append(v)
# Out[40]: {'a': ['1', '2', '4'], 'c': ['abc', 'def', 'xxx'], 'b': ['45', '24', '78']}
Try this method (explanation inline as code comments) -
#Function to turn a list of tuples into a dict after converting integers and keeping string types.
def convert(tup):
di = {}
for a, b in tup:
if b.isdecimal(): #convert to int if possible
b = int(b)
di.setdefault(a, []).append(b)
return di
#convert the input into a list of tuples
k = [tuple(j.split(':')) for i in list_x for j in i.split('_')]
#convert list of tuples into dict
convert(k)
{'a': [1, 2, 4], 'b': [45, 24, 78], 'c': ['abc', 'def', 'xxx']}
list_x = ['a:1_b:45_c:abc','a:2_b:24_c:def','a:4_b:78_c:xxx']
result_dict = {}
for list_element in list_x:
key_val_pair = list_element.split('_')
for key_val in key_val_pair:
key, val = key_val.split(':')
if key not in result_dict:
result_dict[key] = []
result_dict[key].append(val)
print(result_dict)
You need to ensure that your dictionary is dictionary of type string: list that is why I check if the dictionary contains the key and if it does then I push the item and if it doesn't then add a new key with a list containing only the value.
list_x = ['a:1_b:45_c:abc','a:2_b:24_c:def','a:4_b:78_c:xxx']
print(list_x)
dic_x = dict()
for x in list_x:
keyValueList = x.split('_')
for keyValue in keyValueList:
split = keyValue.split(':')
key = split[0]
value = split[1]
if key in dic_x:
dic_x[key].append(value)
else:
dic_x.update({key: [value]})
print(dic_x)
Assuming strings in your list_x always have the same format as: a:integer_b:integer_c:string, you can do this:
dict_x = {'a':[],'b':[],'c':[]}
for s in list_x:
sl = s.split('_')
dict_x['a'].append(int(sl[0][2:]))
dict_x['b'].append(int(sl[1][2:]))
dict_x['c'].append(sl[2][2:])
Maybe this can solve you problem with an easy way without being too much verbose neither compact. It's versatile so you can add as much identifier as you want but as you can see the format of them should be the same
list_x = ['a:1_b:45_c:abc','a:2_b:24_c:def','a:4_b:78_c:xxx']
dict_x ={}
for val in list_x:
elements = val.split('_')
for el in elements:
key, value = el.split(':')[0], el.split(':')[1]
if dict_x.get(key) is None: #If the key it's founded for the first time
dict_x[key] = [value]
else: #If I've already founded the key the data is being appended
dict_x[key].append(value)
print(dict_x)
As you can see the core it's the if that checks if the key founded not exists, in this case create a new array containing the first value founded; otherwise append the value to the actual array.
First split each string based on _ as delimiter and then split it based on : as delimiter, and add each item to a dict
>>> list_x = ['a:1_b:45_c:abc','a:2_b:24_c:def','a:4_b:78_c:xxx']
>>>
>>> from collections import defaultdict
>>> d = defaultdict(list)
>>> for s in list_x:
... for kv in s.split('_'):
... k,v = kv.split(':')
... d[k].append(int(v) if v.isdigit() else v)
...
>>> dict(d)
{'a': [1, 2, 4], 'b': [45, 24, 78], 'c': ['abc', 'def', 'xxx']}
First, let's split the string by ':' and then '_'
list_x = ['a:1_b:45_c:abc','a:2_b:24_c:def','a:4_b:78_c:xxx']
def parse(s):
return [t.split(":") for t in s.split("_")]
parsed_to_lists = [parse(st) for st in list_x]
We now have
[[['a', '1'], ['b', '45'], ['c', 'abc']], [['a', '2'], ['b', '24'], ['c', 'def']], [['a', '4'], ['b', '78'], ['c', 'xxx']]]
we can flatten that by
flat_list = [item for sublist in parsed_to_lists for item in sublist]
flat_list
Which returns
[['a', '1'], ['b', '45'], ['c', 'abc'], ['a', '2'], ['b', '24'], ['c', 'def'], ['a', '4'], ['b', '78'], ['c', 'xxx']]
We want the result as a dictionary of lists, so let's create an empty one
from collections import defaultdict
res = defaultdict(list)
and fill it
for k,v in flat_list:
res[k].append(v)
res
defaultdict(<class 'list'>, {'a': ['1', '2', '4'], 'b': ['45', '24', '78'], 'c': ['abc', 'def', 'xxx']})

Python: Create a dictionary where keys have multiple values

The problem that I have is hard to explain, easy to understand:
I have a list of tuples:
L=[('a','111'),('b','222'),('a','333'),('b','444')]
from this list I want to createa dictionary where the keys are the first elements of the tuples ('a' and 'b') and the values associated are in a list:
expected output:
{'a':['111','333'],'b':['222','444']}
How can I solve this problem?
d={}
for x in range (len(L)):
d[L[x][0]]=[L[x][1]]
return d
but as you can easy understand, the output won't be complete since the list will show just the last value associated to that key in L
You can use setdefault() to set the key in the dict the first time. Then append your value:
L=[('a','111'),('b','222'),('a','333'),('b','444')]
d = {}
for key, value in L:
d.setdefault(key, []).append(value)
print(d)
# {'a': ['111', '333'], 'b': ['222', '444']}
You have to append L[x][1] to an existing list, not replace whatever was there with a new singleton list.
d={}
for x in range (len(L)):
if L[x][0] not in d:
d[L[x][0]] = []
d[L[x][0]].append(L[x][1])
return d
A defaultdict makes this easier:
from collections import defaultdict
d = defaultdict(list)
for x in range(len(L)):
d[L[x][0]].append(L[x][1])
return d
A more idiomatic style of writing this would be to iterate directly over the list and unpack the key and value immediately:
d = defaultdict(list)
for key, value in L:
d[key].append(value)
You can try this:
L = [('a','111'),('b','222'),('a','333'),('b','444')]
my_dict = {}
for item in L:
if item[0] not in my_dict:
my_dict[item[0]] = []
my_dict[item[0]].append(item[1])
print(my_dict)
Output:
python your_script.py
{'a': ['111', '333'], 'b': ['222', '444']}
As pointed by #chepner, you can use defaultdict to.
Basically, with defaultdict you'll not need to check if there is no key yet in your dict.
So it would be:
L = [('a','111'),('b','222'),('a','333'),('b','444')]
my_dict = defaultdict(list)
for item in L:
my_dict[item[0]].append(item[1])
print(my_dict)
And the output:
defaultdict(<class 'list'>, {'a': ['111', '333'], 'b': ['222', '444']})
And if you want to get a dict from the defaultdict, you can simply create a new dict from it:
print(dict(my_dict))
And the output will be:
{'a': ['111', '333'], 'b': ['222', '444']}

split dictionary into two lists , one list is for key, another list is for value

I want to split dictionary into two lists. one list is for key, another list is for value.
And it should be ordered as original
Original list:
[{"car":45845},{"house": 123}]
Expected result:
list1 = ["car", "house"]
list2 = [45845, 123]
fixed_list = [x.items() for x in list]
keys,values = zip(*fixed_list)
list1 = [k for item in [{"car":45845},{"house": 123}] for k,v in item.iteritems()]
list2 = [v for item in [{"car":45845},{"house": 123}] for k,v in item.iteritems()]
For Python 3 use dict.items() instead of dict.iteritems()
original = [{"car":45845},{"house": 123}]
a_dict = {}
for o in original:
a_dict.update(o)
print a_dict
print a_dict.keys()
print a_dict.values()
Output:
{'car': 45845, 'house': 123}
['car', 'house']
[45845, 123]
a =[{"car":45845},{"house": 123}]
list1 = [i.values()[0] for i in a] #iterate over values
list2= [i.keys()[0] for i in a] #iterate over keys

Categories