Python Merge dictionaries of same length but different keys - python

I have two dictionaries of same length but not the same keys like below
dict1 = {"integervalue": None, "floatingValue": None, "stringValue": None}
dict2 = {"0": 10, "1": 0.1020, "2": "XXX"}
I need to update the values of second dictionary to first (dictionaries of same length) and using zip to achieve like below
for (k, v) in zip(dict1, dict2):
dict1[k] = dict2[v]
this does the job and produces output as below
dict1 = {"integervalue": 10, "floatingValue": 0, "stringValue": "XXX"}
or is there any better way to achieve without zip ?

Here's one way to achieve what I think you are after but it does not account for if there are multiple int, float, or str values in the dict2, it modifies the dict1 a bit, and it uses a third dictionary.
dict1 = {str: 'stringValue', int: 'integerValue', float: 'floatingValue'}
dict2 = {"0": 10, "1": 0.1020, "2": "XXX"}
output = {}
for k, v in dict2.items():
output.update({
dict1.get(type(v)): v
})
Output: {'integerValue': 10, 'floatingValue': 0.102, 'stringValue': 'XXX'}
EDIT Could also do for v in dict2.values() since I am not using the k variable.

Assuming the keys always have the same correspondence like in the example you showed, I'd actually make that explicit instead of relying on insertion ordering, which may cause problems. Something like:
key_translation = {
"integerValue": "0",
"floatingValue": "1",
"stringValue": "2"
}
dict1 = {"integerValue": None, "floatingValue": None, "stringValue": None}
dict2 = {"0": 10, "1": 0.1020, "2": "XXX"}
for key in dict1:
dict1[key] = dict2[key_translation[key]]
print(dict1)
# {'integerValue': 10, 'floatingValue': 0.102, 'stringValue': 'XXX'}

Related

I do not understand how to switch keys while using two dictionaries

"""
Given two dictionaries, find the keys they have in common,
and return a new dictionary that maps the corresponding values.
Example:
dict1 == {"a":"alpha", "d":"delta", "x":"xi"}
dict2 == {"b":"bet", "d":"dalet", "l":"lamed", "a":"alef"}
should return:
{"alpha":"alef", "delta":"dalet", "beta":"bet"}
"""
dict1 == {"a":"alpha", "d":"delta", "x":"xi"}
dict2 == {"b":"bet", "d":"dalet", "l":"lamed", "a":"alef"}
new_dict = {}
for key, value in dict1.items():
if value in new_dict:
new_dict[value].append(key)
else:
new_dict[value]=[key]
This is what I have, all I have to do is make it so that the output is what is the same as {"alpha":"alef", "delta":"dalet", "beta":"bet"} which is just switching the keys.
According to your question if two dictionaries are like this:
dict1= {"a":"alpha", "d":"delta", "x":"xi"}
dict2 == {"b":"bet", "d":"dalet", "l":"lamed", "a":"alef"}
comm_keys = set(dict1.keys()).intersection(dict2.keys())
required_dict = {dict1[key]: dict2[key] for key in comm_keys}
# Expected output : {'delta': 'dalet', 'alpha': 'alef'}
One more way which you can do this is to use dictionary comprehension
dict1 = {"a": "alpha", "d": "delta", "x": "xi"}
dict2 = {"b": "bet", "d": "dalet", "l": "lamed", "a": "alef"}
output = {dict1[x]: dict2[x] for x in dict1 if x in dict2}
{'alpha': 'alef', 'delta': 'dalet'}

How to remove empty or None fields in deeply nested dictionary of unknown depth?

I have a dictionary of deeply nested dictionaries and I am trying to remove all k-v pairs that are None or "". The below dictionary d is an example of the input.
d = {
"1": {
"1_1": 'a real value',
"1_2": ""
},
"2": None,
"3": {
"3_1": {
"3_2": None
}
}
}
Normally, to remove empty fields in a dictionary, the command {k:v for k,v in d.items() if v} does the job. But in this case, I want to remove all the nested dictionaries whose values are empty or null, and I can't figure out how to do this. Any ideas?
After d passes through this transformation, all the empty dictionaries whose values are empty should be gone. It should look like this:
{
"1": {
"1_1": 'a real value',
}
}
You can write a function to recursively remove empty dictionaries. For example:
def return_non_empty(my_dict):
temp_dict = {}
for k, v in my_dict.items():
if v:
if isinstance(v, dict):
return_dict = return_non_empty(v)
if return_dict:
temp_dict[k] = return_dict
else:
temp_dict[k] = v
return temp_dict
For example, if d is:
d = {
"1": {
"1_1": 'a real value',
"1_2": ""
},
"2": None,
"3": {
"3_1": {
"3_2": None
}
}
}
then my custom function return_non_empty will return:
>>> return_non_empty(d)
{'1': {'1_1': 'a real value'}}
You can use recursion with a dictionary comprehension:
d = {'1': {'1_1': 'a real value', '1_2': ''}, '2': None, '3': {'3_1': {'3_2': None}}}
def get_d(d):
return {a:c for a, b in d.items() if (c:=(b if not isinstance(b, dict) else get_d(b)))}
print(get_d(d))
Output:
{'1': {'1_1': 'a real value'}}
Note: this solution uses Python's assignment expressions (:=) available in versions >= 3.8. For a solution that does not use this paradigm, please see #Anonymous's answer.
This python function recursively removes dictionary keys whose values are empty, None, False, or 0.
def remove_empty_keys(dictionary):
if isinstance(dictionary, dict):
for key, value in dictionary.copy().items():
if isinstance(value, dict):
remove_empty_keys(value)
if not value:
del(dictionary[key])
Similar to #Ajax1234's answer but this function acts directly on target dictionary rather than outputting a new one.

How to get all values for the same key from key-value pairs in python dictionary

How to iterate over all key value pairs of a dictionary and build all different values list for the same key using python.
Sample data:
"list": [
{
"1": 1
},
{
"1": 8
},
{
"1": 9
},
{
"1": 1
},
{
"2": 8
},
{
"2": 10
}
],
For the above list, I need to build a list like:
[{"1":[1,8,9]}, {"2":[8,10]}]
This will give you what you want
import collections
input_ = {'list': [{'1': 1}, {'1': 8}, {'1': 9}, {'1': 1}, {'2': 8}, {'2': 10}]}
result = collections.defaultdict(list)
for elem in input_['list']:
key, value = next(iter(elem.items())) # best way to extract data from your strange format
if value not in result[key]:
result[key].append(value)
result = [dict(result)] # put it in the strange format you want
outputs
[{'1': [1, 8, 9], '2': [8, 10]}]
However I strongly recommend reconsidering how you structure your data. For example, your input should be a list of tuples, not a list of dictionaries.
this should do the trick - but please notice that doing a dictionary with only one key and value is not the way to save data.
new_dict = {}
for pair in your_list:
for key in pair:
if key in new_dict:
new_dict[key] = new_dict[key].append(pair[key])
else:
new_dict[key] = [pair[key]]
print new_dict
new_dict is a dictionary with key -> list of values mapping

make a dict/json from string with duplicate keys Python

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

Adding multiple values to an existing dictionary as SETS

I have a dictionary where I have the data already inside, i.e. keys have values and some of them have more than one value.
For example:
i = {"a": "111", "b": "222", "c": ["333", "444"]}
How can I change the type of the multiple values? I want them to be sets, not lists, such as:
i = {"a": {"111"}, "b": {"222"}, "c": {"333", "444"}}
One similar post is this one:
How to add multiple values to a dictionary key in python? [closed]
There it is explained how to add multiple elements to a dictionary, but they always seem to be lists.
How to change the type of the multiple values?
OR how to add them to the dictionary as sets, not lists?
Using a dict-comprehension makes converting an existing dict very easy:
i = {"a": "111", "b": "222", 'c': ["333", "444"]}
{k: set(v) if isinstance(v, list) else v for k, v in i.items()}
this converts all values that are lists to sets.
In a single line of code:
>>> i = {"a": "111", "b": "222", "c": ["333", "444"]}
>>> {k: set(v) for k, v in i.items()}
{'b': {'2'}, 'a': {'1'}, 'c': {'444', '333'}}
Or with a few more steps:
>>> i = {"a": "111", "b": "222", "c": ["333", "444"]}
>>> for k, v in i.items():
... i[k] = set(v)
>>> i
{'b': {'2'}, 'a': {'1'}, 'c': {'444', '333'}}
Instead of doing
my_dict['key'] = ['333', '444']
use a set literal:
my_dict['key'] = {'333', '444'}
That looks like a dict literal, but the lack of key: value like things makes it a set.

Categories

Resources