Replace first dictionary value with value from second if blank - python

I would like dict3 to match dict2 after running it through this loop. It doesn't have to be a loop if there is an easier way.
dict1={'key1' : 'val1', 'key2' : ''}
dict2={'key1' : 'val1', 'key2' : 'val2'}
dict3=dict1
#pseudocode
for key in dict1.keys():
if value is not None:
#no need to do anything
else:
dict3[value] = dict2[value]
What I would like is for dict3 to contain keys and values matching dict2.

I believe you need a dict comprehension with .copy
Ex:
dict1 = {'key1' : 'val1', 'key2' : ''}
dict2 = {'key1' : 'val1', 'key2' : 'val2'}
dict3 = {k: v if v else dict2.get(k, v) for k, v in dict1.items() }
print(dict3) #--> {'key1': 'val1', 'key2': 'val2'}

Related

Split links inside a list of values of a Python dictionary

I have a dictionary like this:
dict = {
key1: <http://www.link1.org/abc/f><http://www.anotherlink.com/ght/y2>,
key2: <http://www.link1.org/abc/f><http://www.anotherOneLink.en/ttta/6jk>,
key3: <http://www.somenewlink.xxw/o192/ggh><http://www.link4.com/jklu/wepdo9>,
key4: <http://www.linkkk33.com/fgkjc><http://www.linknew2.com/poii/334hsj>,
...
}
Goal to achieve:
I want to separate the 2 links inside each value of the dictionary, and then count how many times each first value occurs in the entire dictionary. Something like this:
new_dict = {
key1: [<http://www.link1.org/abc/f>, <http://www.anotherlink.com/ght/y2>],
key2: [<http://www.link1.org/abc/f>, <http://www.anotherOneLink.en/ttta/6jk>],
key3: [<http://www.somenewlink.xxw/o192/ggh>, <http://www.link4.com/jklu/wepdo9>],
key4: [<http://www.linkkk33.com/fgkjc>, <http://www.linknew2.com/poii/334hsj>],
...
}
first_value_count = {
<http://www.link1.org/abc/f> : 2,
<http://www.somenewlink.xxw/o192/ggh> : 1,
<http://www.linkkk33.com/fgkjc> : 1,
....
}
My Code:
To split the values I've tried this, but it doesn't work:
new_dict = {k: v[0].split(">") for k, v in dict.items()}
To count the value occurrences in my dictionary:
from collections import Counter
all_dictionary_values = []
for v[0] in new_dict.values():
all_dictionary_values.append(x)
count = Counter(all_dictionary_values)
I have a very big dictionary (1M+ keys), is this the fastest way to count all value occurrences in my dictionary?
I tried your code but it didn't work on my side, so I changed it as follows :
dict = {
'key1' : "<http://www.link1.org/abc/f><http://www.anotherlink.com/ght/y2>",
'key2': "<http://www.link1.org/abc/f><http://www.anotherOneLink.en/ttta/6jk>",
'key3' : "<http://www.somenewlink.xxw/o192/ggh><http://www.link4.com/jklu/wepdo9>",
'key4': "<http://www.linkkk33.com/fgkjc><http://www.linknew2.com/poii/334hsj>",
}
new_dict = {k: v.split("><") for k, v in dict.items()}
new_dict
Output
{'key1': ['<http://www.link1.org/abc/f', 'http://www.anotherlink.com/ght/y2>'],
'key2': ['<http://www.link1.org/abc/f',
'http://www.anotherOneLink.en/ttta/6jk>'],
'key3': ['<http://www.somenewlink.xxw/o192/ggh',
'http://www.link4.com/jklu/wepdo9>'],
'key4': ['<http://www.linkkk33.com/fgkjc',
'http://www.linknew2.com/poii/334hsj>']}
And we add the counter here :
from collections import Counter
all_dictionary_values = []
for v in new_dict.values():
all_dictionary_values.append(v[0]+">")
count = Counter(all_dictionary_values)
count
Ouput
Counter({'<http://www.link1.org/abc/f': 2,
'<http://www.somenewlink.xxw/o192/ggh': 1,
'<http://www.linkkk33.com/fgkjc': 1})

Creating nested dictionary from two lists one of which contains dictionaries

Very similar to this question but with an added caveat.
I have two lists identical in length. One contains my keys, and the other contains a list of dictionaries belonging to said keys. Example below (yes the Nones are intentional)
keys = ['key1', 'key2, 'key3']
vals = [[{'subkey1': 'val1', 'subkey2': 'val2'}], [{'subkey1: 'val2'},None],[{'subkey1':'val3'}, {'subkey3':'val1}, None, None]]
What I'd like to do is match each dictionary in each list to a key to create a nested dict.
So something like below:
final = {'key1':{'subkey1': 'val1', 'subkey2': 'val2'}, 'key2':{'subkey1': 'val2'}, 'key3':{'subkey1':'val3'}, {'subkey3':'val1'}}
I know we can use dictionary comprehension to do this. I created a dictionary of empty dicts.
s = {}
for i in keys:
for v in vals:
s[i] = {}
break
Then I wrote the following to iterate through the list of dicts I'd like to pair up accounting for the non dictionary values in my list.
x = 0
while x < len(keys):
for i in keys:
for element in vals[x]:
if isinstance(element, dict) == True:
s[str(i)].append(element)
else:
print('no')
x=x+1
However when I run this, I get AttributeError: 'NoneType' object has no attribute 'append'
How can I append to a dictionary using this for loop?
For the less readable dictionary comprehension solution
keys = ['key1', 'key2', 'key3']
vals = [
[{'subkey1': 'val1', 'subkey2': 'val2'}],
[{'subkey1': 'val2'}, None],
[{'subkey1': 'val3'}, {'subkey3':'val1'}, None, None]
]
s = {
k: {
sk: sv for d in (x for x in v if x is not None) for sk, sv in d.items()
} for k, v in zip(keys, vals)
}
Gives
{'key1': {'subkey1': 'val1', 'subkey2': 'val2'},
'key2': {'subkey1': 'val2'},
'key3': {'subkey1': 'val3', 'subkey3': 'val1'}}
This can be done fairly easily using a defaultdict:
from collections import defaultdict
keys = ['key1', 'key2', 'key3']
vals = [
[{'subkey1': 'val1', 'subkey2': 'val2'}],
[{'subkey1': 'val2'},None],
[{'subkey1':'val3'}, {'subkey3':'val1'}, None, None]
]
final = defaultdict(dict)
for idx, key in enumerate(keys):
for d in vals[idx]:
if d is not None:
final[key].update(d)
Output:
defaultdict(<class 'dict'>, {
'key1': {'subkey1': 'val1', 'subkey2': 'val2'},
'key2': {'subkey1': 'val2'},
'key3': {'subkey1': 'val3', 'subkey3': 'val1'}
})
can't use append on a dict
try this maybe?
keys = ['key1', 'key2', 'key3']
vals = [[{'subkey1': 'val1', 'subkey2': 'val2'}], [{'subkey1': 'val2'},None],[{'subkey1':'val3'}, {'subkey3':'val1'}, None, None]]
s = {}
for i in keys:
s[i] = {}
for i, key in enumerate(keys):
for element in vals[i]:
if isinstance(element, dict) == True:
s[str(key)].update(element)
print(s)
Output:
{'key1': {'subkey1': 'val1', 'subkey2': 'val2'}, 'key2': {'subkey1': 'val2'}, 'key3': {'subkey1': 'val3', 'subkey3': 'val1'}}

removing all the keys with the same value in dictionary

I want to get a new dictionary by removing all the keys with the same value (keys are differents, values are the same)
For example: Input:
dct = {'key1' : [1,2,3], 'key2': [1,2,6], 'key3': [1,2,3]}
expected output:
{'key2': [1, 2, 6]}
key1 and key3 was deleted because they shared same values.
I have no idea about it?
You can do this by creating a dictionary based on the values. In this case the values are lists which are not hashable so convert to tuple. The values in the new dictionary are lists to which we append any matching key from the original dictionary. Finally, work through the new dictionary looking for any values where the list length is greater than 1 - i.e., is a duplicate. Then we can remove those keys from the original dictionary.
d = {'key1' : [1,2,3], 'key2': [1,2,6], 'key3': [1,2,3]}
control = {}
for k, v in d.items():
control.setdefault(tuple(v), []).append(k)
for v in control.values():
if len(v) > 1:
for k in v:
del d[k]
print(d)
Output:
{'key2': [1, 2, 6]}
I created a list of counts which holds information about how many times an item is in the dictionary. Then I copy only items which are there once.
a = {"key1": [1,2,3], "key2": [1,2,6], "key3": [1,2,3]}
# find how many of each item are there
counts = list(map(lambda x: list(a.values()).count(x), a.values()))
result = {}
#copy only items which are in the list once
for i,item in enumerate(a):
if counts[i] == 1:
result[item] = a[item]
print(result)
As given by the OP, the simplest solution to the problem:
dct = {'key1' : [1,2,3], 'key2': [1,2,6], 'key3': [1,2,3]}
print({k:v for k, v in dct.items() if list(dct.values()).count(v) == 1})
Output:
{'key2': [1, 2, 6]}
One loop solution:
dict_ = {'key1' : [1,2,3], 'key2': [1,2,6], 'key3': [1,2,3]}
key_lookup = {}
result = {}
for key, value in dict_.items():
v = tuple(value)
if v not in key_lookup:
key_lookup[v] = key
result[key] = value
else:
if key_lookup[v] is not None:
del result[key_lookup[v]]
key_lookup[v] = None
print(result)
Output:
{'key2': [1, 2, 6]}
dct = {'key1' : [1,2,3], 'key2': [1,2,6], 'key3': [1,2,3]}
temp = list(dct.values())
result = {}
for key, value in dct.items():
for t in temp:
if temp.count(t) > 1:
while temp.count(t) > 0:
temp.remove(t)
else:
if t == value:
result[key] = value
print(result)
Output:
{'key2': [1, 2, 6]}

Update dictionary key(s) by drop starts with value from key in Python

I have a dictionary dict:
dict = {'drop_key1': '10001', 'drop_key2':'10002'}
The key(s) in dict startswith drop_, i would like to update dict by dropping drop_ value from key(s):
dict = {'key1': '10001', 'key2':'10002'}
What is the best approach to do it?
something like
d1 = {'drop_key1': '10001', 'drop_key2':'10002'}
d2 = {k[5:]:v for k,v in d1.items()}
print(d2)
output
{'key1': '10001', 'key2': '10002'}
One approach is, for each key value in the dictionary, you can replace the part of the string with the new string value. For instance:
d = {k.replace('drop_', ''): v for k, v in d.items() if k.strip().startswith('drop_')}
or you can define a function, and get the index of the searched string ("drop_"). If the search string index is 0, then remove it. For instance:
def change_key(key, search):
start_idx = key.find(search)
if start_idx == 0:
key = key.replace(search, "")
return key
d = {change_key(k, search="drop_"): v for k, v in d.items()}
Result:
{'key1': '10001', 'key2': '10002'}
Note that if you use a method, then you can guarantee to remove the search string if it is at the beginning of the string. For instance:
d = {' drop_key1': '10001', 'drop_key2': '10002'}
d = {change_key(k, search="drop_"): v for k, v in d.items()}
Result:
{' drop_key1': '10001', 'key2': '10002'}

Get a string list from a word

I'm trying to invert items of a dictionary containing strings as key and string list as value:
dico = {'key1': [],
'key2': [],
'key3': ['value1', 'value1'],
'key4': ['value2', 'value2'],
'key5': ['value3'],
'key6': ['value1', 'value2', 'value3']}
new_dict = {}
for key, values in dico.items():
if values:
for value in values:
try:
if key not in new_dict[value]:
new_dict[value].append(key)
except KeyError:
new_dict[values[0]] = list(key)
else:
print('ERROR')
Here's the result expected:
#Expected
new_dict = {'value1': ['key3', 'key6'],
'value2': ['key4', 'key6'],
'value3': ['key5', 'key6']}
#Reality
new_dict = {'value1': ["k", "e", "y", "3", "k", "e", "y", "6"],
'value2': ["k", "e", "y", "4", "k", "e", "y", "6"],
'value3': ["k", "e", "y", "5", "k", "e", "y", "6"]}
I noticed if I change that:
new_dict[values[0]] = list(key)
by that:
new_dict[values[0]] = []
new_dict[values[0]].append(key)
It actually works but is there another way to do it in one line ?
You are turning your keys to lists:
new_dict[values[0]] = list(key)
That'll produce a list with individual characters. Use a list literal instead:
new_dict[values[0]] = [key]
You can use the dict.setdefault() method to handle missing keys in new_dict to simplify your code. It looks like you want to produce sets instead; sets track unique values and saves you having to do explicit tests for duplicates.
for key, values in dico.items():
for value in values:
new_dict.setdefault(value, set()).add(key)
You can always turn those sets back to lists afterwards:
new_dict = {key: list(values) for key, values in new_dict.items()}
Demo:
>>> dico = {'key1': [],
... 'key2': [],
... 'key3': ['value1', 'value1'],
... 'key4': ['value2', 'value2'],
... 'key5': ['value3'],
... 'key6': ['value1', 'value2', 'value3']}
>>> new_dict = {}
>>> for key, values in dico.items():
... for value in values:
... new_dict.setdefault(value, set()).add(key)
...
>>> new_dict
{'value3': set(['key6', 'key5']), 'value2': set(['key6', 'key4']), 'value1': set(['key3', 'key6'])}
>>> {key: list(values) for key, values in new_dict.items()}
{'value3': ['key6', 'key5'], 'value2': ['key6', 'key4'], 'value1': ['key3', 'key6']}
Iterate every item from main dico dictionary.
Check if value is present or not.
Iterate every item from value.
Use set method to remove duplicate values.
Add to new_dict dictionary where value is key and key is list value.
code:
dico = {'key1': [],
'key2': [],
'key3': ['value1', 'value1'],
'key4': ['value2', 'value2'],
'key5': ['value3'],
'key6': ['value1', 'value2', 'value3']}
new_dict = {}
for key, values in dico.items():
if values:
for value in set(values):
try:
new_dict[value].append(key)
except:
new_dict[value] = [key]
import pprint
pprint.pprint(new_dict)
Output:
$ python test.py
{'value1': ['key3', 'key6'],
'value2': ['key6', 'key4'],
'value3': ['key6', 'key5']}

Categories