How can I flat list in dictionary if I have something like this:
Object {'a': '48',
'b': '24',
'c':[{'cA':'20', 'cB':'42', 'cC':'55'}, {'c1':'21', 'c2':'43','c3':'58'}],
'd':'44',
'e':'32',}
That's parsed XML file, in XML C has a structure like this:
<p name = "a">48<\p>
<p name = "b">24<\p>
<list name ="C">
<item>
<cA>20<\cA>
<cB>42<\cB>
<cC>55<\cC>
<\item>
<item>
<c1>21<\c1>
<c2>43<\c2>
<c3>58<\c3>
<\item>
<\list>
<p name = "D">44<\p>
<p name = "e">32<\p>
Desired output would be :
Object {'a':'48',
'b':'24',
'cA':'20',
'cB':'42',
'cC':'55',
'c1':'21',
'c2':'43',
'c3':'58'
'd':'44',
'e':'32'}
supposing that you have fixed depth and contain "flat" dictionaries (that's a lot of "supposing", I know), you can iterate through the input dict and check for type of the values.
If value is a list, update the output dict with the items of the list, else update with the original items
d= {'a1': '48',
'b': '24',
'c':[{'cA':'20', 'cB':'42', 'cC':'55'}, {'c1':'21', 'c2':'43', 'c3':'58'}],
'd':'44',
'e':'32'}
new_d = {}
for k,v in d.items():
if isinstance(v,list):
for v1 in v:
new_d.update(v1)
else:
new_d[k] = v
result:
{'c2': '43', 'a1': '48', 'c3': '58', 'b': '24', 'cC': '55', 'd': '44', 'cA': '20', 'cB': '42', 'e': '32', 'c1': '21'}
Related
I have a dictionary as
dict1={'A': ['15', '3'],'B': ['14', '3']}
and my first value of each key is my total so A's total is 15 and B's total is 14.
I have another dictionary dict2 as
dict2={'A': {'A.X': '20.41%',
'A.Y': '30.59%',
'B.X': '20.09%',
'B.Y': '10.00%',
'C.X': '8.04%',
'C.Y': '10.87%'},
'B': {'B.X': '35.15%',
'B.Y': '50.85%',
'C.X': '0.00%',
'C.Y': '0.00%',
'D.X': '14.00%',
'D.Y': '0.00%'}}
I would like to apply each dict1-key's total to my dict2 values of the same keys to get the ratio of total such as
dict3={'A': {'A.X': '3.06',
'A.Y': '4.59',
'B.X': '3.01',
'B.Y': '1.5',
'C.X': '1.2',
'C.Y': '1.63'},
'B': {'B.X': '4.92',
'B.Y': '7.12',
'C.X': '0',
'C.Y': '0',
'D.X': '1.96',
'D.Y': '0'}}
I thought I may start with
new_dict = { key : dict1[key]*dict2[key][0] for key in dict1 if key in dict2 }
but this didnt work. Any help is appreciated
p.s I am new to python and thanks in advance.
You can get the result you want by two layers of iteration:
>>> dict3 = {}
>>> for k1, v1 in dict2.items():
... total = int(dict1[k1][0]) / 100
... dict3[k1] = {k2: f'{float(v2[:-1]) * total:.3g}' for k2, v2 in v1.items()}
...
>>> dict3
{'A': {'A.X': '3.06', 'A.Y': '4.59', 'B.X': '3.01', 'B.Y': '1.5', 'C.X': '1.21', 'C.Y': '1.63'}, 'B': {'B.X': '4.92', 'B.Y': '7.12', 'C.X': '0', 'C.Y': '0', 'D.X': '1.96', 'D.Y': '0'}}
Any way to create dictionary of dictionaries of lists in one line?
names = ['alex', 'ben', 'coby']
age = ['20', '30', '40', '50']
name_age = {n: {} for n in names}
for n in names:
name_age[n] = {a: {} for a in age}
Nesting such as below does not work.
name_age = {n: {{a: {} for a in age}} for n in names}
The fastest way of constructing a dictionary based on two lists is iterating them at the same time with zip. This will work:
names = ['alex', 'ben', 'coby']
age = ['20', '30', '40', '50']
name_age = dict(zip(names, age))
print(name_age)
>>> {'alex': '40', 'ben': '50', 'coby': '20'}
names = ['alex', 'ben', 'coby']
ages = ['20', '30', '40', '50']
result = { names[index]:ages[index] for index in range(len(names)) }
print(result)
{'alex': '20', 'ben': '30', 'coby': '40'}
I want to combine the list of ages of the groups which are having a repeated name...
My code:
dic1 = {'g1': ['45', '35', '56', '65'], 'g2': ['67', '76'], 'g3':['8', '96']}
dic2 = {'g1': ['akshay', 'swapnil', 'parth','juhi'], 'g2': ['megha', 'varun'], 'g3': ['gaurav', 'parth']}
for key2,name_list in dic2.items():
for name in name_list:
if name=='parth':
for key1,age_list in dic1.items():
if key1==key2:
print(age_list)
The output is:
['45', '35', '56', '65']
['8', '96']
I want the output as:
['45', '35', '56', '65', '8', '96']
Can someone help me with this?
there's more pythonic than that, you need to chain the lists. Also, no need for so many loops. A one-liner should do.
dic1 = {'g1': ['45', '35', '56', '65'], 'g2': ['67', '76'], 'g3':['8', '96']}
dic2 = {'g1': ['akshay', 'swapnil', 'parth','juhi'], 'g2': ['megha', 'varun'], 'g3': ['gaurav', 'parth']}
import itertools
result = list(itertools.chain.from_iterable(dic1[k] for k,v in dic2.items() if 'parth' in v))
>>> result
['45', '35', '56', '65', '8', '96']
A variant without itertools would be:
result = [x for k,v in dic2.items() if 'parth' in v for x in dic1[k]]
With a dict of sets instead of a dict of lists:
dic2 = {'g1': {'akshay', 'swapnil', 'parth','juhi'}, 'g2': {'megha', 'varun'}, 'g3': {'gaurav', 'parth'}}
those turn your O(N**3) algorithm into a O(N) algorithm (because in lookup in a list is O(N) but O(1) in a set).
If you have a missing key, just replace dic1[k] by dic1.get(k,[]) or even dic1.get(k) or [].
You could either use itertools as mentioned in other answers, or just simplify your own code.
There is no need to have a three layer nested for loop. As python only allows
unique keys, you could eliminate the innermost for loop like so:
output_list = []
for key, name_list in dic2.items():
if "parth" in name_list:
output_list += dic1[key]
print(output_list)
As and when you get the required age list which is to be displayed, add it to the output_list with a simple +=.
Though the above code is easier to understand, I recommend using itertools.
Currently, I have the following weird nested dictionary:
d = {'start': {'0': {'start', 'near'}, '1': {'start'}}, 'near': {'1': {'end'}}, 'end': {}}
And the following list:
l = ['1', '0', '1', 'x', '0', '1']
If one of the values in l are not in one of the keys and values in the dictionary, remove it from the list.
So for example, in the list, there is an "x" and I am trying to see if there is anyway I can remove it with either l.remove() or if del / pop is better.
The thing that is giving me troubles is the dictionary.
What I have going so far:
d = {'start': {'0': {'start', 'near'}, '1': {'start'}}, 'near': {'1': {'end'}}, 'end': {}}
l = ['1', '0', '1', 'x', '0', '1']
for key, value in d.items():
for keys, values in value.items():
for number in l:
Get the set of keys:
keys = set.union(*[set(x.keys()) for x in d.values()])
#{'0', '1'}
Filter out the non-keys:
result = [item for item in l if item in keys]
#['1', '0', '1', '0', '1']
I am very new to python (python 3.2) and I have been struggling with a difficult problem. I have two dictionary with listed lists:
d1 = {
'mammals': ['dog', '5', 'cat', '4', 'mouse', '4', 'bat', '3'],
'bird': ['robin', '8', 'bluejay', '6', 'goose', '5', 'cardinal', '5']
}
and
d2 = {
'mammals': ['cow', '5', 'horse', '4', 'cat', '4', 'dog', '3', 'beaver', '3'],
'bird': ['bluejay', '9', 'goose', '8', 'eagle', '8', 'robin', '7', 'duck', '6', 'cardinal', '5']
}
In each dictionary, the pair name-number (for instance, 'dog', '5') correspond to how many instances of said item where present in the original data bases.
What I need is to merge the two dictionaries in a way that information about quantity preserved (again, in the example, the new dictionary would have 'dog', '5', '3'. So that the merged dictionary would look somewhat like (I am not necessarily committed to nested dictionaries. I wrote it this way for easiness of visualization. The important thing is too keep the information):
d_merged = {
'mammals': [{'dog': ['5', '3']}, {'cat': ['4', '4']}, {'mouse': '4'}, {'bat': '3'} , {'cow': '5'},
{'horse': '4'}, {'beaver': '3'}],
'bird': [{'robin': ['8', '7']}, {'bluejay': ['6', '9']}, {'goose': ['5','8']}, {'cardinal': ['5',
'5']}, {'eagle': '8'}, {'duck', '6'}]
}
I have tried various things with tuples, nested dictionaries and other possibilities, but the result has been a mess. It would mean a lot if someone could point me in a good direction to solve this. I thank you very much
The most readable way to do it is probably as follows:
output = {}
for key in d1.keys():
output[key] = {}
lst = d1[key]
for name, count in (lst[i:i+2] for i in range(0, len(lst), 2)):
output[key][name] = (int(count),)
for key in d2.keys():
if key not in output:
output[key] = {}
lst = d2[key]
for name, count in (lst[i:i+2] for i in range(0, len(lst), 2)):
if name in output[key].keys():
output[key][name] += (int(count),)
else:
output[key][name] = (int(count),)
In incomprehensible dictionary comprehensions, you can do it in two steps
d = {k: {a: int(b) for a, b in (v[i:i+2] for i in range(0, len(v), 2))}
for k, v in d.items()}
To turn them into dictionaries of dictionaries, e.g.
{'mammals': {'cat': 4, 'cow': 5, 'dog': 3, 'beaver': 3, 'horse': 4},
'bird': {'goose': 8, 'duck': 6, 'eagle': 8, 'bluejay': 9, 'robin': 7, 'cardinal': 5}}
Then
output = {k1: {k2: (d1.get(k1, {}).get(k2), d2.get(k1, {}).get(k2))
for k2 in set(list(d1.get(k1, {}).keys()) + list(d2.get(k1, {}).keys()))}
for k1 in set(list(d1.keys()) + list(d2.keys()))}
To combine the two.
Note that these methods both work even if there are different keys at the two levels (e.g. adding d1['reptiles'] = {'lizard': 10}).
first you can change d1 and d2 to be dictionaries that is easier to work with:
[note that list[::2] is sublist that holds all the item in the even indices, and list[1::2] holds the odds.]
>>> dc1 = {}
>>> for family in d1.keys():
l = d1[family]
dc1[family] = {l[::2][family]:[l[1::2][family]] for family in range(len(l)/2)}
>>> dc2 = {}
>>> for family in d1.keys():
l = d2[family]
dc2[family] = {l[::2][family]:[l[1::2][family]] for family in range(len(l)/2)}
now dc1 and dc2 are these:
>>> dc1
{'mammals': {'bat': ['3'], 'mouse': ['4'], 'dog': ['5'], 'cat': ['4']},
'bird': {'goose': ['5'], 'cardinal': ['5'], 'robin': ['8'], 'bluejay': ['6']}}
>>> dc2
{'mammals': {'beaver': ['3'], 'horse': ['4'], 'dog': ['3'], 'cow': ['5'], 'cat': ['4']},
'bird': {'eagle': ['8'], 'bluejay': ['9'], 'goose': ['8'], 'cardinal': ['5'], 'duck': ['6'], 'robin': ['7']}}
and then you just need to combine them
>>> d_merged = {}
>>> families = set(d1.keys()+d2.keys())
>>> family2animals = {family:list(set(dc1[family].keys()+dc2[family].keys())) for family in families}
>>> for family in families:
d_merged[family] = [{animal:dc1[family].get(animal,[])+dc2[family].get(animal,[])} for animal in family2animals[family]]