I have nested dictionary with lists like this
{
'a': 1,
'x':[
{'b': 1,
'c': [
{'z': 12},
{'z': 22},
]
},
{'b': 2,
'c': [
{'z': 10},
{'z': 33},
]
}
]
}
And I want to convert it to list of flat dictionaries i form like this.
[
{'a': 1, 'b': 1, 'z': 12},
{'a': 1, 'b': 1, 'z': 22},
{'a': 1, 'b': 2, 'z': 10},
{'a': 1, 'b': 2, 'z': 33},
]
Any idea how to achieve that?
The following produces the requested result:
[{'a': 1, 'b': 1, 'z': 12}, {'a': 1, 'b': 2, 'z': 10}]
Use at your own risk. The following was only tested on your example.
from itertools import product
def flatten(D):
if not isinstance(D, dict): return D
base = [(k, v) for k, v in D.items() if not isinstance(v, list)]
lists = [[flatten(x) for x in v] for k, v in D.items() if isinstance(v, list)]
l = []
for p in product(*lists):
r = dict(base)
for a in p:
for d in a:
r.update(d)
l.append(r)
return l
The following tests above.
d = {
'a': 1,
'x':[
{'b': 1,
'c': [
{'z': 12}
]
},
{'b': 2,
'c': [
{'z': 10}
]
}
]
}
print flatten(d)
A possible solution is:
#!/usr/bin/env python3
d = {
'a': 1,
'x': [
{
'b': 1,
'c': [
{'z': 12}
]
},
{
'b': 2,
'c': [
{'z': 10}
]
}
]
}
res = [{"a": 1, "b": x["b"], "z": x["c"][0]["z"]} for x in d["x"]]
print(res)
This assumes that there is only one a (with a fixed value of 1) and x element and this element is added to the comprehension manually.
The other two elements (b and z) are taken from x array with a list comprehension.
To learn more about how comprehensions work read the following:
Python Documentation - 5.1.4. List Comprehensions
Python: List Comprehensions
PS. You are supposed to first show what you have tried so far and get help on that. Take a look at SO rules before posting your next question.
Related
I just wanna sort these dictionaries with some values from an input file.
def sortdicts():
listofs=[]
listofs=splitndict()
print sorted(listofs)
The splitndict() function has this output:
[{'a': 1, 'b': 2}, {'c': 2, 'd': 4}, {'a': 7, 'c': 3}, {'y': 5, 'x': 0}]
While the input is from another file and it's:
a 1
b 2
c 2
d 4
a 7
c 3
x 0
y 5
I used this to split the dictionary:
def splitndict():
listofd=[]
variablesRead=readfromfile()
splitted=[i.split() for i in variablesRead]
d={}
for lines in splitted:
if lines:
d[lines[0]]=int(lines[1])
elif d=={}:
pass
else:
listofd.append(d)
d={}
print listofd
return listofd
The output file should look like this:
[{'y': 5, 'x': 0}, {'a': 1, 'b': 2}, {'c': 2, 'd': 4}, {'a': 7, 'c': 3}
This output because :
It needs to be sorted by the lowest value from each dictionary key.
array = [{'y': 5, 'x': 0}, {'a': 1, 'b': 2}, {'c': 2, 'd': 4}, {'a': 7, 'c': 3}]
for the above array:
array = sorted(array, lambda element: min(element.values()))
where "element.values()" returns all values from dictionary and "min" returns the minimum of those values.
"sorted" passes each dictionary (an element) inside the lambda function one by one. and sorts on the basis of the result from the lambda function.
x = [{'y': 5, 'x': 0}, {'a': 1, 'b': 2}, {'c': 2, 'd': 4}, {'a': 7, 'c': 3}]
sorted(x, key=lambda i: min(i.values()))
Output is
[{'y': 5, 'x': 0}, {'a': 1, 'b': 2}, {'c': 2, 'd': 4}, {'a': 7, 'c': 3}]
I have the following dict structure:
{12345: {2006: [{'a': 1, 'b': 2}, {'a': 3, 'b': 4}, {'a': 1, 'b': 5}]}, 12346: {2007: [{'a': 2, 'b': 7}, {'a': 1, 'b': 9}, {'a': 1, 'b': 12}]}}
I want to be able to filter based on the keys of 'a' or 'b'
for example if 'a' is 1 the my filtered dict would look like:
{12345: {2006: [{'a': 1, 'b': 2}, {'a': 1, 'b': 5}]}, 12346: {2007: [{'a': 1, 'b': 9}, {'a': 1, 'b': 12}]}}
I have the following for loop which gets me down to where I have the inner dict's I want, but I am not sure how to put it back into a dict of the same structure.
d = {12345: {2006: [{'a': 1, 'b': 2}, {'a': 3, 'b': 4}, {'a': 1, 'b': 5}]}, 12346: {2007: [{'a': 2, 'b': 7}, {'a': 1, 'b': 9}, {'a': 1, 'b': 12}]}}
d_filter = {}
for item_code in d.keys():
for year in d[item_code]:
for item_dict in d[item_code][year]:
if item_dict['a'] == 1:
print(item_dict) # how to put this back in d_filter?
producing:
{'a': 1, 'b': 2}
{'a': 1, 'b': 5}
{'a': 1, 'b': 9}
{'a': 1, 'b': 12}
I am guessing there is a better way to filter that I can not find, or something with dictionary comprehension that my small mind can not grasp.
Any help would be appreciated.
Here's a dictionary comprehension that does just that; dct is your initial dictionary:
d = {k: {ky: [d for d in vl if d['a']==1] for ky, vl in v.items()}
for k, v in dct.items()}
print d
# {12345: {2006: [{'a': 1, 'b': 2}, {'a': 1, 'b': 5}]}, 12346: {2007: [{'a': 1, 'b': 9}, {'a': 1, 'b': 12}]}}
You can change the inner filter (i.e. d['a']==1) to the dict key and/or value of your choice.
You could do something like this:
filtered = {
item_code: {
year: [item for item in items if item['a'] == 1]
for year, items in years.items()
}
for item_code, years in d.items()
}
Which results in:
{12345: {2006: [{'a': 1, 'b': 2}, {'a': 1, 'b': 5}]},
12346: {2007: [{'a': 1, 'b': 9}, {'a': 1, 'b': 12}]}}
I looking the most elegant way to get this:
{'i_1': {'a': 33, 't': 4}, 'i_2': {'a': 9, 't': 0}}
From this:
{'i_1': {'a': 33, 'b': 55, 't': 4}, 'i_2': {'a': 9, 'b': 11, 't': 0}}
Each inner dict can have a lot of a, b, ..., z keys.
for now I have this::
In [3]: {k:dict(a=d[k]['a'], t=d[k]['t']) for k in d.keys()}
Out[3]: {'i_1': {'a': 33, 't': 4}, 'i_2': {'a': 9, 't': 0}}
but it's not very elegant
You can make your code a little bit more readable by using items instead of keys:
{k: dict(a=v['a'], t=v['t']) for k, v in d.items())
Here you go. This functions takes a dict in a format you specified and a list of keys that have to be removed from inner dictionaries:
def remove_inner_keys(data: dict, inner_keys_to_remove: list) -> dict:
result = dict()
for outer_key in data.keys():
partial_result = dict()
for inner_key in data[outer_key]:
if inner_key not in inner_keys_to_remove:
partial_result[inner_key] = data[outer_key][inner_key]
result[outer_key] = partial_result
return result
Testing:
data = { 'i_1': { 'a': 33, 'b': 55, 't': 4 }, 'i_2': { 'a': 9, 'b': 11, 't': 0 } }
print(str(remove_inner_keys(data, ["b"])))
output:
{'i_2': {'a': 9, 't': 0}, 'i_1': {'a': 33, 't': 4}}
import copy
def foo(d):
d_copy = copy.deepcopy(d)
for key in d_copy:
print(key, d[key])
if isinstance(d[key], dict):
foo(d[key])
if key == 'b':
d.pop(key)
I have a list containing numbers:
[123, 32, 434]
I need to convert it to JSON format which looks like this:
[{'a': 1, 'b': 123}, {'a': 2, 'b': 32},{'a': 3, 'b': 434}]
so, I need to add a running index to the list and then convert it to JSON.
Using enumerate and list comprehensions
>>> lst = [123, 32, 434]
>>> data = [{'a': k, 'b': v} for k, v in enumerate(lst, 1)]
>>> data
[{'a': 1, 'b': 123}, {'a': 2, 'b': 32}, {'a': 3, 'b': 434}]
As per my understanding, i did some like this. May be its help full for you.
a = [2, 7, 55, 92]
l = []
for n in enumerate(a):
l.append({"a":n[0]+1, "b":n[1]})
print l
Output:
[{'a': 1, 'b': 2}, {'a': 2, 'b': 7}, {'a': 3, 'b': 55}, {'a': 4, 'b': 92}]
This may be a duplicate but the closest I could find was Comparing 2 lists consisting of dictionaries with unique keys in python which did not work for me.
So I have two lists of dictionaries.
y = [{'a': 3, 'b': 4, 'c': 5}, {'a': 1, 'b': 2, 'c': 3}]
y = [{'a': 4, 'b': 5, 'c': 6}, {'a': 1, 'b': 2, 'c': 3}]
How do I compare these two lists so my compare results in the intersection of the two lists. I can't convert it to set since it says unhashable type (dict)
Your question and it's title seem at odds with each other.
The intersection of the 2 lists would be the common elements of both list. The question title requests the elements that are not in both lists. Which is it that you want?
For the intersection, it is not very efficient (being O(n^2) in time), but this list comprehension will do it:
>>> a = [{'a': 3, 'b': 4, 'c': 5}, {'a': 1, 'b': 2, 'c': 3}]
>>> b = [{'a': 4, 'b': 5, 'c': 6}, {'a': 1, 'b': 2, 'c': 3}]
>>> [d for d in a if d in b]
[{'a': 1, 'b': 2, 'c': 3}]
y1 = [{'a': 3, 'b': 4, 'c': 5}, {'a': 1, 'b': 2, 'c': 3}]
y2 = [{'a': 4, 'b': 5, 'c': 6}, {'a': 1, 'b': 2, 'c': 3}]
print [x for x in y1 if x in y2] # prints [{'a': 1, 'c': 3, 'b': 2}]
A dict (or list) is not hashable, however, a tuple is. You can convert the list of dicts to a set of tuples. Perform the intersection and then convert back
the code to convert to a set-of-tuples
y_tupleset = set(tuple(sorted(d.items())) for d in y)
the code to convert back the intersected set-of-tuples to a list-of-dicts
y_dictlist = [dict(it) for it in list(y_tupleset)]
Thus, the full code would be:
y0 = [{'a': 3, 'b': 4, 'c': 5}, {'a': 1, 'b': 2, 'c': 3}]
y1 = [{'a': 4, 'b': 5, 'c': 6}, {'a': 1, 'b': 2, 'c': 3}]
y0_tupleset = set(tuple(sorted(d.items())) for d in y0)
y1_tupleset = set(tuple(sorted(d.items())) for d in y1)
y_inter = y0_tupleset.intersection(y1_tupleset)
y_inter_dictlist = [dict(it) for it in list(y_inter)]
print(y_inter_dictlist)
# prints the following line
[{'a': 1, 'c': 3, 'b': 2}]
edit: d.items() is valid on python3, for python2, it should be replaced with d.iteritems()
Pick your poison:
y1 = [{'a': 3, 'b': 4, 'c': 5}, {'a': 1, 'b': 2, 'c': 3}]
y2 = [{'a': 4, 'b': 5, 'c': 6}, {'a': 1, 'b': 2, 'c': 3}]
y3 = [{'a': 1, 'b': 2, 'c': 3}, {'a': 4, 'b': 2, 'c': 6}]
# Returns a list of keys that are in both dictionaries
def intersect_keys(d1, d2):
return [k for k in d1 if k in d2]
# Returns a list of values that are in both dictionaries
def intersect_vals(d1, d2):
return [v for v in d1.itervalues() if v in d2.itervalues()]
# Returns a list of (key,value) pairs that are in both dictionaries
def intersect_pairs(d1, d2):
return [(k,v) for (k,v) in d1.iteritems() if k in d2 and d2[k] == v]
print(intersect_keys(*y1)) # ['a', 'c', 'b']
print(intersect_vals(*y1)) # [3]
print(intersect_pairs(*y1)) # []
print(intersect_keys(*y2)) # ['a', 'c', 'b']
print(intersect_vals(*y2)) # []
print(intersect_pairs(*y2)) # []
print(intersect_keys(*y3)) # ['a', 'c', 'b']
print(intersect_vals(*y3)) # [2]
print(intersect_pairs(*y3)) # [('b', 2)]
Note: the examples compare the two elements of the y* list, which was how I interpreted your question. You could of course use something like:
print(intersect_pairs(y1[0], y2[0]))
To compute the intersection the first dictionary in the y1 and y2 lists.