How to check for multiple values in dict in Python - python

dict1 = {'galaxy': 5, 'apple': 6, 'nokia': 5}
Is there is a way to show the keys in a dict with the same values in a dict?
target_value = 5
new_dict = {}
for key, value in dict1:
if value == target_value:
new_dict[key] = value
desired output:
dict1 = {'galaxy':5, 'nokia':5}

If I understand you correctly, you're looking for something like that:
>>> d = {'galaxy': 5, 'apple': 6, 'nokia': 5}
>>> { k:v for k,v in d.items() if v==5 }
{'nokia': 5, 'galaxy': 5}

Related

Select key and one value out of tuples with multiple values per key to create new dictionary

I started recently learning programming Python and I am running into a problem. I tried to solve this myself, unsuccessfully.
I have a dictionary with a formatted string as a key and tuples with 3 values per key.
dict1 = { “a;2;1;1;” : ( 1, 2, 3), “a;3;2;1;” : ( 4, 5, 6)}
I want to create a new dictionary dict2 with all keys from dict1 and only the third value from each key.
dict2 = { “a;2;1;1;” : 3, “a;3;2;1;” : 6}
In these examples I used only two key-value pairs, the real dictionary has ten thousand of key-value pairs.
Any suggestions?
Do it with a simple iteration:
dict2 = dict()
for k in dict1:
dict2[k] = dict1[k][2]
Or use a dict-comprehension to do it in a single line:
dict2 = {k: dict1[k][2] for k in dict1}
2 Line solution, could probably be done in a more 'python' way but this will work:
dict1 = {'a;2;1;1;' : ( 1, 2, 3), 'a;3;2;1;' : ( 4, 5, 6)}
dict2 = {}
# You just need these two lines here
for k in dict1:
dict2[k] = dict1[k][2]
print(dict2)
dict1 = { 'a;2;1;1;' : ( 1, 2, 3), 'a;3;2;1;' : ( 4, 5, 6)}
dict2 = {}
for k in dict1.keys():
dict2[k] = dict1[k][2]
This can be done with a dictionary comprehension also:
dict1 = { “a;2;1;1;” : ( 1, 2, 3), “a;3;2;1;” : ( 4, 5, 6)}
dict2 = {x: y for (x,(_,_,y)) in dict1.items()}

Python dictionary format change splitting keys

How could i go from this format of dictionary
{'A.B': 7, 'C.D': 5, 'A.D': 34}
to this:
{'A': {'B':7, D:34} , 'C': {'D': 5} }
Meaning of key 'A.B' is that i go from A to B and its value means 7 times, so what i am trying to do is change this format so that my dictionary key is where i go from and its value its a dictionary with his destinations (one or more) and the times of each.
I have tried several things, but for now things are not working out.
I have tried using for with a new dictionary but it overrides my keys.
Using defaultdict:
d = {'A.B': 7, 'C.D': 5, 'A.D': 34}
from collections import defaultdict
formatted_d = defaultdict(dict)
for k, v in d.items():
top_key, bottom_key = k.split('.')
formatted_d[top_key][bottom_key] = v
Without defaultdict:
formatted_d = {}
for k, v in d.items():
top_key, bottom_key = k.split('.')
if top_key not in formatted_d:
formatted_d[top_key] = {}
formatted_d[top_key][bottom_key] = v
Clean and easy to understand with collections.defaultdict:
from collections import defaultdict
dct = {'A.B': 7, 'C.D': 5, 'A.D': 34}
new_dict = defaultdict(dict)
for key, value in dct.items():
root, descendant = key.split(".")
new_dict[root][descendant] = value
print(new_dict)
This yields
defaultdict(<class 'dict'>, {'A': {'B': 7, 'D': 34}, 'C': {'D': 5}})
Quick approach:
d = {'A.B': 7, 'C.D': 5, 'A.D': 34}
dicts_init = {key.split('.')[0]: {} for key, value in d.items()}
for key, value in d.items():
root_k, val = key.split(".")
dicts_init[root_k][val] = value
print(dicts_init)
Outputs:
{'A': {'B': 7, 'D': 34}, 'C': {'D': 5}}
d = {'A.B': 7, 'C.D': 5, 'A.D': 34}
result = {}
for key in d:
current, destination = key.split('.')
times = d.get(key)
if current not in result.keys():
result[current] = {destination: int(times)}
else:
result[current][destination] = int(times)
print(result)

How do I check to see if values in a dict are the exact same?

I currently have a dictionary d with key: string, and values is another dict.
In the d dictionary values, how can I check which key and values are ALL the same?
Example Dictionary:
zybook, zybooks, zybookz are keys. There can be more than three keys, but I only put two for now. And then the values of d are another dict with {file name : number}
d = {"zybook":
{
"noodle.json": 5,
"testing.json": 1,
"none.json": 5
},
"zybooks":
{
"noodle.json": 5,
"ok.json": 1
},
"zybookz":
{
"noodle.json": 5
}
}
Expected Output:
Because {"noodle.json": 5} {"noodle.json": 5} are both the same in zybook, zybooks, and zybookz the output will create another dictionary with all 3 matches.
{"noodle.json": 5}
My attempt:
I honestly don't know how to approach this.
d = {"zybook": { "noodle.json": 5, "testing.json": 1, "none.json": 5},
"zybooks": {"noodle.json": 5, "ok.json": 1},
"zybookz": {"noodle.json": 5}
}
for key, value in d.items():
for k, v in value.items():
if
from functools import reduce
sets = (set(val.items()) for val in d.values())
desired = dict(reduce(set.intersection, sets))
print(desired)
# {'noodle.json': 5}
We first form sets out of the file_name:num pairs of each dictionary. Then, reduce cumulatively looks each set and reduces them to the desired result by taking intersection of those sets. Lastly, converting to a dict as needed.
Try this:
from collections import Counter
res = {z[0]: z[1] for z, count in Counter([(k, v) for x in d for k, v in d[x].items()]).items() if count == len(d)}
With only the use of embedded Python methods
new = []
for v in d.values():
new+=list(v.items())
# [('noodle.json', 5), ('testing.json', 1), ('none.json', 5), ('noodle.json', 5), ('ok.json', 1)]
cnt_dict = {v:new.count(v) for v in new}
# {('noodle.json', 5): 3, ('testing.json', 1): 1, ('none.json', 5): 1, ('ok.json', 1): 1}
d2 = {k[0]:k[1] for k,v in cnt_dict.items() if v > 1}
print(d2)
# {'noodle.json': 5}

int values in dict appending as list

I have a for loop which is going through multiple dictionaries and adding the values under common keys. The input dictionary has keys that are strings and values that are int's. For some reason its adding the values as lists of one value (e.g. {"01":[12],[44]}). I want it to add the int on its own but cant get that working for some reason. I'm using the code below, is there something i am missing ?
dw = defaultdict()
dw = {}
for key, value in listb.items():
dw[key].append(value)
If you want to forgo all good practice and not use defaultdict(list), you can use setdefault and call it every single time you choose to add a value. This is inefficient and not idiomatic, but it will work.
In [1]: from collections import defaultdict
In [2]: a = defaultdict(list)
In [3]: b = {}
In [4]: a[1].append(1)
In [5]: b.setdefault(1, []).append(1)
In [6]: a
Out[6]: defaultdict(list, {1: [1]})
In [7]: b
Out[7]: {1: [1]}
In [8]:
As long as the values in the dicts are ints (not lists):
dw = {}
for key, value in listb.items():
try: # Key exists in dictionary and value is a list
dw[key].append(value)
except KeyError: # Key does not yet exist in dictionary
dw[key] = value
except AttributeError: # Key exist in dictionary and value is not a list
dw[key] = [dw[key], value]
If you mean to add key/value pairs to the dictionary (and not append to an array), it's:
for key, value in listb.items():
dw[key] = value
EDIT: or is it something like this you're after?
listb = {'1': 3, '2': 5}
dw = {'1': 5, '2': 9}
for key, value in listb.items():
if key not in dw.keys():
dw[key] = []
else:
dw[key] = [dw[key]]
dw[key].append(value)
which gives dw = {'2': [9, 5], '1': [5, 3]}
If you have a list like listb = [{'a': 1, 'b': 2}, {'a': 3, 'b': 4, 'c': 5}, {'b': 1}], you can try this:
dw = {}
for d in listb:
for k, v in d.items():
if k in dw:
if isinstance(dw[k], list):
dw[k].append(v)
elif isinstance(dw[k], int):
dw[k] = [dw[k], v]
else:
dw[k] = v
print(dw)
{'a': [1, 3], 'b': [2, 4, 1], 'c': 5}
>>>

What's the most pythonic way to merge 2 dictionaries, but make the values the average values?

d1 = { 'apples': 2, 'oranges':5 }
d2 = { 'apples': 1, 'bananas': 3 }
result_dict = { 'apples': 1.5, 'oranges': 5, 'bananas': 3 }
What's the best way to do this?
Here is one way:
result = dict(d2)
for k in d1:
if k in result:
result[k] = (result[k] + d1[k]) / 2.0
else:
result[k] = d1[k]
This would work for any number of dictionaries:
dicts = ({"a": 5},{"b": 2, "a": 10}, {"a": 15, "b": 4})
keys = set()
averaged = {}
for d in dicts:
keys.update(d.keys())
for key in keys:
values = [d[key] for d in dicts if key in d]
averaged[key] = float(sum(values)) / len(values)
print averaged
# {'a': 10.0, 'b': 3.0}
Update: #mhyfritz showed a way how you could reduce 3 lines to one!
dicts = ({"a": 5},{"b": 2, "a": 10}, {"a": 15, "b": 4})
averaged = {}
keys = set().union(*dicts)
for key in keys:
values = [d[key] for d in dicts if key in d]
averaged[key] = float(sum(values)) / len(values)
print averaged
Your question was for the most 'Pythonic' way.
I think for a problem like this, the Pythonic way is one that is very clear. There are many ways to implement the solution to this problem! If you really do have only 2 dicts then the solutions that assume this are great because they are much simpler (and easier to read and maintain as a result). However, it's often a good idea to have the general solution because it means you won't need to duplicate the bulk of the logic for other cases where you have 3 dictionaries, for example.
As an addendum, phant0m's answer is nice because it uses a lot of Python's features to make the solution readable. We see a list comprehension:
[d[key] for d in dicts if key in d]
Use of Python's very useful set type:
keys = set()
keys.update(d.keys())
And generally, good use of Python's type methods and globals:
d.keys()
keys.update( ... )
keys.update
len(values)
Thinking of and implementing an algorithm to solve this problem is one thing, but making it this elegant and readable by utilising the power of the language is what most people would deem 'Pythonic'.
(I would use phant0m's solution)
Yet another way:
result = dict(d1)
for (k,v) in d2.items():
result[k] = (result.get(k,v) + v) / 2.0
A Counter and some Generators are useful in this situation
General Case:
>>> d1 = { 'apples': 2, 'oranges':5 }
>>> d2 = { 'apples': 1, 'bananas': 3 }
>>> all_d=[d1,d2]
>>> from collections import Counter
>>> counts=Counter(sum((d.keys() for d in all_d),[]))
>>> counts
Counter({'apples': 2, 'oranges': 1, 'bananas': 1})
>>> s=lambda k: sum((d.get(k,0) for d in all_d))
>>> result_set=dict(((k,1.0*s(k)/counts[k]) for k in counts.keys()))
>>> result_set
{'apples': 1.5, 'oranges': 5.0, 'bananas': 3.0}
d1 = { 'apples': 2, 'oranges':5 }
d2 = { 'apples': 1, 'bananas': 3, 'oranges':0 }
dicts = [d1, d2]
result_dict = {}
for dict in dicts:
for key, value in dict.iteritems():
if key in result_dict:
result_dict[key].append(value)
else:
result_dict[key] = [value]
for key, values in result_dict.iteritems():
result_dict[key] = float(sum(result_dict[key])) / len(result_dict[key])
print result_dict

Categories

Resources