So, I need to plot something with matplotlib, and all was going perfect up until this error. Basically, what I need is to turn the following:
[
{
"foo":1,
"bar":2
},
{
"foo":8,
"baz":3
}
]
into something like this:
[
{
"foo":1,
"bar":2,
"baz":0
},
{
"foo":8,
"baz":3,
"bar":0
}
]
Is there any way this can be done?
One way is to calculate the union of your keys and then iterate via a for loop.
keys = set().union(*lst)
for d in lst:
for k in keys - d.keys():
d[k] = 0
print(lst)
[{'foo': 1, 'bar': 2, 'baz': 0},
{'foo': 8, 'baz': 3, 'bar': 0}]
Since we're posting answers... There's an easier way. Simply turn your dicts into defaultdicts wherever it is that you're defining them. - defaultdict(int, your_dictionary)
You can then access this dict for your plot regardless of non-existent keys since if they don't exist the defaultdict will just return 0 here as you want. No point reinventing the wheel here.
If keys is the list of keys and L is the list of dictionaries then:
for d in L:
for k in keys:
d.setdefault(k, 0)
sets each missing key to 0.
Related
The information inside the arrays is in the "reverse" order of how I want it. Ideally it could be sorted by the dates within the array but I'm 100% certain just reversing the order would work.
By using something like this:
sorted(Dictionary[self], key=lambda i: i[1][0], reverse=True)
I know that the above JUST sorts the arrays themselves into reverse order and not the data inside the array into reverse order.
With the Dictionary like this (all items are a file name)
Dictionary = {'a':[XPJulianDay(Timefurthestinpastfromnow), ... XPJulianDay(timeclosest2currnttime)], 'b':[RQJulianDay(Timefurthestinpastfromnow), ... RQJulianDay(timeclosest2currnttime)], 'c':[WSJulianDay(Timefurthestinpastfromnow), ... WSJulianDay(timeclosest2currnttime)] ..... (9 different ones total) }
turning into this
Dictionary = {'a':[XPJulianDay(timeclosest2currnttime), ... XPJulianDay(Timefurthestinpastfromnow)], 'b':[RQJulianDay(timeclosest2currnttime), ... RQJulianDay(Timefurthestinpastfromnow)], 'c':[WSJulianDay(timeclosest2currnttime), ... WSJulianDay(Timefurthestinpastfromnow)] .... }
You can try that:
Dictionary.update({ k: sorted(v) for k, v in Dictionary.items() })
It updates the dictionary with its own keys, with sorted values.
Example:
>>> Dictionary = {"a": [7,6,1,2], "b": [8,0,2,5] }
>>> Dictionary.update({ k: sorted(v) for k, v in Dictionary.items() })
>>> Dictionary
{'a': [1, 2, 6, 7], 'b': [0, 2, 5, 8]}
>>>
Note that a new dictionary is created for the call to .update() using a dict comprehension.
If needed you can replace sorted() by reversed() ; but reversed() returns an iterator so if you want a list you need to call it with list() (it is better to keep the iterator if you can).
Example with reversed:
>>> Dictionary = {"a": [7,6,1,2], "b": [8,0,2,5] } ; Dictionary.update({ k: reversed(v) for k, v in Dictionary.items() })
>>> Dictionary
{'a': <list_reverseiterator object at 0x7f537a0b3a10>, 'b': <list_reverseiterator object at 0x7f537a0b39d0>}
>>>
You can use the dict comprehension as stated by #mguijarr or use dict and zip
Dictionary = dict(zip(Dictionary, map(sorted, Dictionary.values()))))
But if your keys really are just the 'a', 'b', ... then why are you using a dict? Just use a list...
Let us imagine the following dictionary
dictionary = {
"key1": {
"value": [1, 3, 5],
},
"key2": {
"value": [1, 2, -1],
},
}
Is it possible to set all the "values" to [] without iterating over the dictionary keys? I want something like dictionary[]["value"]=[] such that all "value" attributes are set to []. But that doesn't work.
Because you need to avoid iteration, here is a little hacky way of solving the case.
Convert dictionary to string, replace and then back to dictionary:
import re, ast
dictionary = {
"key1": {
"value": [1, 3, 5],
},
"key2": {
"value": [1, 2, -1],
},
}
print(ast.literal_eval(re.sub(r'\[.*?\]', '[]', str(dictionary))))
# {'key1': {'value': []}, 'key2': {'value': []}}
I'm going to take a different tack here. Your question is a little misinformed. The implication is that it's "better" to avoid iterating dictionary keys. As mentioned, you can iterate over dictionary values. But, since internally Python stores dictionaries via two arrays, iteration is unavoidable.
Returning to your core question:
I want something like dictionary[]["value"]=[] such that all "value"
attributes are set to [].
Just use collections.defaultdict:
from collections import defaultdict
d = {k: defaultdict(list) for k in dictionary}
print(d['key1']['value']) # []
print(d['key2']['value']) # []
For the dictionary structure you have defined, this will certainly be more efficient than string conversion via repr + regex substitution.
If you insist on explicitly setting keys, you can avoid defaultdict at the cost of an inner dictionary comprehension:
d = {k: {i: [] for i in v} for k, v in dictionary.items()}
{'key1': {'value': []}, 'key2': {'value': []}}
just wondering, before I start to work on a function. I always like to hear some pythonic solutions.
I am trying to get keys and values from nested dictionaries:
for an example:
a = {'one': {'animal': 'chicken'},
'two': {'fish': {'sea':'shark'}}}
is there any pythonic way to get values from nested dictionary? Like get straight to value of 'fish'?
Thanks in advance
If you want to find all the items with the "fish" key in the nested dictionary, you can modify this answer flatten nested python dictionaries-compressing keys - answer #Imran
import collections
def get_by_key_in_nested_dict(d, key, parent_key='', sep='_'):
items = []
for k, v in d.items():
new_key = parent_key + sep + k if parent_key else k
if key==k:
items.append((new_key, v))
if isinstance(v, collections.MutableMapping):
items.extend(get_by_key_in_nested_dict(v, key, new_key, sep).items())
return dict(items)
with,
test = {
'one': {
'animal': 'chicken'
},
'two': {
'fish': {
'sea':'shark',
'fish':0
}
},
'fish':[1,2,3]
}
get_by_key_in_nested_dict(test,"fish")
You get all the items that have the key "fish"
{
'fish': [1, 2, 3],
'two_fish': {'fish': 0, 'sea': 'shark'},
'two_fish_fish': 0
}
I have a string that could be parsed as a JSON or dict object. My string variable looks like this :
my_string_variable = """{
"a":1,
"b":{
"b1":1,
"b2":2
},
"b": {
"b1":3,
"b2":2,
"b4":8
}
}"""
When I do json.loads(my_string_variable), I have a dict but only the second value of the key "b" is kept, which is normal because a dict can't contain duplicate keys.
What would be the best way to have some sort of defaultdict like this :
result = {
"a": 1,
"b": [{"b1": 1, "b2": 2}, {"b1": 3, "b2": 2, "b4": 8}],
}
I have already looked for similar questions but they all deal with dicts or lists as an input and then create defaultdicts to handle the duplicate keys.
In my case I have a string variable and I would want to know if there is a simple way to achieve this.
something like the following can be done.
import json
def join_duplicate_keys(ordered_pairs):
d = {}
for k, v in ordered_pairs:
if k in d:
if type(d[k]) == list:
d[k].append(v)
else:
newlist = []
newlist.append(d[k])
newlist.append(v)
d[k] = newlist
else:
d[k] = v
return d
raw_post_data = '{"a":1, "b":{"b1":1,"b2":2}, "b": { "b1":3, "b2":2,"b4":8} }'
newdict = json.loads(raw_post_data, object_pairs_hook=join_duplicate_keys)
print (newdict)
Please note that above code depends on value type, if type(d[k]) == list. So if original string itself gives a list then there could be some error handling required to make the code robust.
Accepted answer is perfectly fine. I just wanted to show another approach.
So at first, you dedicate a list for values in order to easily accumulate next values. At the end, you call pop on the lists which have only one item. This means that the list doesn't have duplicate values:
import json
from collections import defaultdict
my_string_variable = '{"a":1, "b":{"b1":1,"b2":2}, "b": { "b1":3, "b2":2,"b4":8} }'
def join_duplicate_keys(ordered_pairs):
d = defaultdict(list)
for k, v in ordered_pairs:
d[k].append(v)
return {k: v.pop() if len(v) == 1 else v for k, v in d.items()}
d = json.loads(my_string_variable, object_pairs_hook=join_duplicate_keys)
print(d)
output:
{'a': 1, 'b': [{'b1': 1, 'b2': 2}, {'b1': 3, 'b2': 2, 'b4': 8}]}
I have question about Dictionaries in Python.
here it is:
I have a dict like dict = { 'abc':'a', 'cdf':'b', 'gh':'a', 'fh':'g', 'hfz':'g' }
Now i want to get all Key-Elements by the same value and save it in a new dict.
The new Dict should be look like:
new_dict = { 'b':('cdf'), 'a':('abc','gh'), 'g':('fh','hfz')}
If you are fine with lists instead of tuples in the new dictionary, you can use
from collections import defaultdict
some_dict = { 'abc':'a', 'cdf':'b', 'gh':'a', 'fh':'g', 'hfz':'g' }
new_dict = defaultdict(list)
for k, v in some_dict.iteritems():
new_dict[v].append(k)
If you want to avoid the use of defaultdict, you could also do
new_dict = {}
for k, v in some_dict.iteritems():
new_dict.setdefault(v, []).append(k)
Here's a naive implementation. Someone with better Python skills can probably make it more concise and awesome.
dict = { 'abc':'a', 'cdf':'b', 'gh':'a', 'fh':'g', 'hfz':'g' }
new_dict = {}
for pair in dict.items():
if pair[1] not in new_dict.keys():
new_dict[pair[1]] = []
new_dict[pair[1]].append(pair[0])
print new_dict
This produces
{'a': ['abc', 'gh'], 'b': ['cdf'], 'g': ['fh', 'hfz']}
If you do specifically want tuples as the values in your new dictionary, you can still use defaultdict, and use tuple concatenation. This solution works in Python 3.4+:
from collections import defaultdict
source = {'abc': 'a', 'cdf': 'b', 'gh': 'a', 'fh': 'g', 'hfz': 'g'}
target = defaultdict(tuple)
for key in source:
target[source[key]] += (key, )
print(target)
Which will produce
defaultdict(<class 'tuple'>, {'a': ('abc', 'gh'), 'g': ('fh', 'hfz'), 'b': ('cdf',)})
This will probably be slower than generating a dictionary by list insertion, and will create more objects to be collected. So, you can build your dictionary out of lists, and then map it into tuples:
target2 = defaultdict(list)
for key in source:
target2[source[key]].append(key)
for key in target2:
target2[key] = tuple(target2[key])
print(target2)
Which will give the same result as above.
It can be done this way too, without using any extra functions .
some_dict = { 'abc':'a', 'cdf':'b', 'gh':'a', 'fh':'g', 'hfz':'g' }
new_dict = { }
for keys in some_dict:
new_dict[some_dict[keys]] = [ ]
for keys in some_dict:
new_dict[some_dict[keys]].append(keys)
print(new_dict)