I have a python dict like below:
{ '1': {'a': '0.6', 'b': '0.8', 'c': '2','d': '0.5'},
'2': {'a': '0.7', 'b': '0.9', 'c': '0.1','d': '0.2'},
'3': {'a': '0.5', 'b': '0.8', 'c': '3'},
}
How could I get the following result?
('2','a','0.7') ('2',b','0.9') ('3','c', '3') ('1','d', '0.5')
Well, here is the code for it (just 5 lines):
total = []
for i in ['a', 'b', 'c', 'd']:
kv = max(a.iterkeys(), key=(lambda key: float(a[key][i]) if i in a[key].keys() else -9.0))
hv = a[kv][i]
total.append((kv, i, hv))
print total
Output:
[('2', 'a', '0.7'), ('2', 'b', '0.9'), ('3', 'c', '3'), ('1', 'd', '0.5')]
-9.0 is just a random low number.
x={ '1': {'a': '0.6', 'b': '0.8', 'c': '2','d': '0.5'},
'2': {'a': '0.7', 'b': '0.9', 'c': '0.1','d': '0.2'},
'3': {'a': '0.5', 'b': '0.8', 'c': '3'},
}
d={}
for i,j in x.iteritems():
for k,m in j.iteritems():
d.setdefault(k,[0,0])
if j[k]>d[k][0]:
d[k]=(j[k],i)
print [(j[1],i,j[0]) for i,j in d.items()]
You can use additional dict to do your job.
Output:[('2', 'a', '0.7'), ('3', 'c', '3'), ('2', 'b', '0.9'), ('1', 'd', '0.5')]
I agree the question is a bit vague.. I recommend you dont use strings as values.. use int or float if you can in the dictionaries, also does not specify if python 2.x or 3.x
but I think you are after something like this..
def filter_dict(values):
result = collections.Counter()
for value in values.keys():
for k, v in values[value].items():
v = float(v)
result[k] = v if v > result[k] else result[k]
return result
this is how it behaves:
class FilterDictTest(unittest.TestCase):
def test_filter_dict(self):
# Arrange
actual = {
'1': {'a': '0.6', 'b': '0.8', 'c': '2', 'd': '0.5'},
'2': {'a': '0.7', 'b': '0.9', 'c': '0.1', 'd': '0.2'},
'3': {'a': '0.5', 'b': '0.8', 'c': '3'}
}
expected = {
'a': 0.7,
'b': 0.9,
'c': 3,
'd': 0.5
}
# Act & Assert
self.assertEquals(filter_dict(actual), expected)
A little late here.
#!/usr/bin/env python3.5
# entry
entry = {'1': {'a': '0.6', 'b': '0.8', 'c': '2','d': '0.5'}, '2': {'a': '0.7', 'b': '0.9', 'c': '0.1','d': '0.2'}, '3': {'a': '0.5', 'b': '0.8', 'c': '3'}}
# identify keys
all_categories = []
for number, dct in entry.items():
for key, val in dct.items():
all_categories = all_categories + list(dct.keys())
all_categories = set(all_categories)
# Get max values
max_values = {category:None for category in all_categories}
for category in all_categories:
for number, dct in entry.items():
if category in dct.keys():
if max_values[category] is None:
max_values[category] = (number, dct[category])
elif float(max_values[category][1]) < float(dct[category]):
max_values[category] = (number, dct[category])
output = [(number, category, value) for (category, (number, value)) in max_values.items()]
print (output)
Output:
[('2', 'a', '0.7'), ('1', 'd', '0.5'), ('2', 'b', '0.9'), ('3', 'c', '3')]
Not exactly in the order you expected them, but the values are correct. It's not the most elegant solution, though.
I iterate a second time in dict to compare values.
values = []
for key in d:
for skey in d[key]:
max = 0
_key_ = ''
for _ in d:
if d[_].has_key(skey):
if d[_][skey]>max:
max = d[_][skey]
_key_ = _
if (_key_, skey, max) not in values:
values.append((_key_, skey, max))
print values
Related
I have two lists
a = ['b','c','a','d','v']
g = [{'c':'1'},{'c':'2'},{'c':'3'},{'d':'1'},{'d':'2'}]
I want to match the key in the dictionary in the list g to the elements in list a, if they are matched, the elements in list g will be inserted into list a.
The desired outcome is:
['b','c',{'c':'1'},{'c':'2'},{'c':'3'},'a','d',{'d':'1'},{'d':'2'},'v']
Try:
a = ["b", "c", "a", "d", "v"]
g = [{"c": "1"}, {"c": "2"}, {"c": "3"}, {"d": "1"}, {"d": "2"}]
tmp = {}
for d in g:
for k in d:
tmp.setdefault(k, []).append(d)
out = []
for v in a:
out.append(v)
out.extend(tmp.get(v, []))
print(out)
Prints:
['b', 'c', {'c': '1'}, {'c': '2'}, {'c': '3'}, 'a', 'd', {'d': '1'}, {'d': '2'}, 'v']
Try using sorted:
print(sorted(a + g, key=lambda x: list(x)[0]))
Output:
['a', 'b', 'c', {'c': '1'}, {'c': '2'}, {'c': '3'}, 'd', {'d': '1'}, {'d': '2'}, 'e']
a = ['a','b','c','d','e']
g = [{'c':'1'},{'c':'2'},{'c':'3'},{'d':'1'},{'d':'2'},{'z':'1'}]
for dic in g:
for key in dic:
if key in a:
a.append(dic)
print(a)
#output ['a', 'b', 'c', 'd', 'e', {'c': '1'}, {'c': '2'}, {'c': '3'}, {'d': '1'}, {'d': '2'}]
After this, you can do sorting using lambda if required.
Suppose, there is a dictionary like
my_dict = {'A': {'5', '7', '9', '3'},
'B': {'4', '8','3'},
'C': {'5', '3', '2', '9'},
'D': {'1','6', '8','3'},
'E': {'4','3','5'}}
Now the output should be like {A,C} because they have most number of common values.
dct = {'A': {'5', '7', '9', '3'}, 'B': {'4', '8','3'}, 'C': {'5', '3', '2', '9'}, 'D': {'1','6', '8','3'}, 'E': {'4','3','5'}}
ans = [None, None]
mx = 0
for i in dct:
for j in dct:
if i != j and len(dct[i].intersection(dct[j])) > mx:
ans = [i, j]
mx = len(dct[i].intersection(dct[j]))
As there are sets contained, to find number of common elements, we have intersection method.
>>> ans
['A', 'C']
Although, its worth noting that this code would always produce a pair. If you want more number of elements, the number of loops is going to increase accordingly.
I have dictionary something like:
d1 = {'0': {'a'}, '1': {'b'}, '2': {'c', 'd'}, '3': {'E','F','G'}}
and I want result like this
d2 = {'a': '0', 'b': '1', 'c': '2', 'd': '2', 'E': '3', 'F': '3', 'G': '3'}
so I tried
d2 = dict ((v, k) for k, v in d1.items())
but value is surrounded by set{}, so it didn't work well...
is there any way that I can fix it?
You could use a dictionary comprehension:
{v:k for k,vals in d1.items() for v in vals}
# {'a': '0', 'b': '1', 'c': '2', 'd': '2', 'E': '3', 'F': '3', 'G': '3'}
Note that you need an extra level of iteration over the values in each key here to get a flat dictionary.
Another dict comprehension:
>>> {v: k for k in d1 for v in d1[k]}
{'a': '0', 'b': '1', 'c': '2', 'd': '2', 'E': '3', 'F': '3', 'G': '3'}
Benchmark comparison with yatu's:
from timeit import repeat
setup = "d1 = {'0': {'a'}, '1': {'b'}, '2': {'c', 'd'}, '3': {'E','F','G'}}"
yatu = "{v:k for k,vals in d1.items() for v in vals}"
heap = "{v:k for k in d1 for v in d1[k]}"
for _ in range(3):
print('yatu', min(repeat(yatu, setup)))
print('heap', min(repeat(heap, setup)))
print()
Results:
yatu 1.4274586000000227
heap 1.4059823000000051
yatu 1.4562267999999676
heap 1.3701727999999775
yatu 1.4313863999999512
heap 1.3878657000000203
Another benchmark, with a million keys/values:
setup = "d1 = {k: {k+1, k+2} for k in range(0, 10**6, 3)}"
for _ in range(3):
print('yatu', min(repeat(yatu, setup, number=10)))
print('heap', min(repeat(heap, setup, number=10)))
print()
yatu 1.071519999999964
heap 1.1391495000000305
yatu 1.0880677000000105
heap 1.1534022000000732
yatu 1.0944767999999385
heap 1.1526202000000012
Here's another possible solution to the given problem:
def flatten_dictionary(dct):
d = {}
for k, st_values in dct.items():
for v in st_values:
d[v] = k
return d
if __name__ == '__main__':
d1 = {'0': {'a'}, '1': {'b'}, '2': {'c', 'd'}, '3': {'E', 'F', 'G'}}
d2 = flatten_dictionary(d1)
print(d2)
I'm trying to calculate difference between two dictionaries to return a specific value.
I've entered different values which should return different results, but the result remains unchanged.
diets = {"normal" : {'p': '32.50', 'c': '60', 'f': '40.86'},
"oncology" : {'p': '35', 'c': '52.50', 'f': '37.63'},
"cardiology" : {'p': '32.50', 'c': '30', 'f': '26.88'},
"diabetes" : {'p': '20', 'c': '27.50', 'f': '27.95'},
"kidney" : {'p': '15', 'c': '55', 'f': '23.65'}}
amounts = {'p': p, 'c': c, 'f': f}
value = { k : diets[k] for k in set(diets) - set(amounts) }
calculate_error = min(value)
print(calculate_error)
When i input 32, 60 and 40, the returned result should be normal, but oncology is returned instead
You should look at the values you are creating when you do this:
set(diets)
This is just a list of keys.
{'cardiology', 'diabetes', 'kidney', 'normal', 'oncology'}
When you subtract the other list of keys, you just get the original list because no values are in common.
You need to actually step through the items and do the subtraction to get the differences. Then you can find the sum of the diffs and the min of that sum.
One way would be:
diets = {"normal" : {'p': '32.50', 'c': '60', 'f': '40.86'},
"oncology" : {'p': '35', 'c': '52.50', 'f': '37.63'},
"cardiology" : {'p': '32.50', 'c': '30', 'f': '26.88'},
"diabetes" : {'p': '20', 'c': '27.50', 'f': '27.95'},
"kidney" : {'p': '15', 'c': '55', 'f': '23.65'}}
amounts = {'p': 32., 'c': 60., 'f': 40.}
mins = [(diet, sum([abs(amounts[k] - float(d[k])) for k in amounts])) for diet, d in diets.items()]
the_min = min(mins, key = lambda x: x[1])
mins will be:
[('normal', 1.3599999999999994),
('oncology', 12.869999999999997),
('cardiology', 43.620000000000005),
('diabetes', 56.55),
('kidney', 38.35)]
the_min will be:
('normal', 1.3599999999999994)
It looks you totally confused what value would be
>>> diets = {"normal" : {'p':'32.50', 'c':'60', 'f':'40.86'},
... "oncology" : {'p':'35', 'c':'52.50', 'f':'37.63'},
... "cardiology" : {'p':'32.50', 'c':'30', 'f':'26.88'},
... "diabetes" : {'p':'20', 'c':'27.50', 'f':'27.95'},
... "kidney" : {'p':'15', 'c':'55', 'f':'23.65'}}
>>> set(diets)
{'kidney', 'cardiology', 'oncology', 'normal', 'diabetes'}
>>> amounts = {'p':32, 'c':60, 'f':40}
>>> set(amounts)
{'c', 'f', 'p'}
>>> set(diets) - set(amounts)
{'cardiology', 'diabetes', 'kidney', 'oncology', 'normal'}
>>> value = { k : diets[k] for k in set(diets) - set(amounts) }
>>> value
{'cardiology': {'p': '32.50', 'c': '30', 'f': '26.88'},
'diabetes': {'p': '20', 'c': '27.50', 'f': '27.95'},
'kidney': {'p': '15', 'c': '55', 'f': '23.65'},
'oncology': {'p': '35', 'c': '52.50', 'f': '37.63'},
'normal': {'p': '32.50', 'c': '60', 'f': '40.86'}}
>>> min(value)
'cardiology'
that said I would expect that you to get cardiology, i.e. the min from diets.keys()
That said, note that the values in the diets are str, e.g. '32.50', You will need to convert these before any calculations.
This question already has answers here:
How to merge dicts, collecting values from matching keys?
(17 answers)
Closed 3 years ago.
I would like to append dictionary in a for loop such that i get a concatenated dictionary. Also, it is not necessary that keys of all dictionary will be exactly same.
For eq
one={'a': '2', 'c': 't', 'b': '4'}
two={'a': '3.4', 'c': '7.6'}
three={'a': 1.2, 'c': 3.4, 'd': '2.3'}
Output:
combined={'a':['2','3.4','1.2'],'b':'4','c':['t','7.6','3.4'],
'd':'2.3'}
Now coming to original question:
Every time a for loop iterates, a dictionary will be generated and i would like to append it.
Something like:
emptydict={}
for x in z:
newdict=x.dict()
emptydict.append(newdict)
print(emptydict)
try this
one={'a': '2', 'c': 't', 'b': '4'}
two={'a': '3.4', 'c': '7.6'}
three={'a': 1.2, 'c': 3.4, 'd': '2.3'}
df = pd.DataFrame([one,two,three])
a b c d
0 2 4 t NaN
1 3.4 NaN 7.6 NaN
2 1.2 NaN 3.4 2.3
df.to_dict(orient='list')
Output
{'a': ['2', '3.4', 1.2],
'b': ['4', nan, nan],
'c': ['t', '7.6', 3.4],
'd': [nan, nan, '2.3']}
You can try something like this.
one = {'a': '2', 'c': 't', 'b': '4'}
two = {'a': '3.4', 'c': '7.6'}
three = {'a': 1.2, 'c': 3.4, 'd': '2.3'}
new_dict = {}
list_dict = [one, two, three]
for d in list_dict:
for key in d:
if key not in new_dict:
new_dict[key] = []
new_dict[key].append(d[key])
print(new_dict)
Output : {'a': ['2', '3.4', 1.2], 'c': ['t', '7.6', 3.4], 'b': ['4'], 'd': ['2.3']}
I have used your examples to do so -
one = {'a': '2', 'c': 't', 'b': '4'}
two = {'a': '3.4', 'c': '7.6'}
three = {'a': 1.2, 'c': 3.4, 'd': '2.3'}
dicts = [one, two, three]
for dictionary in dicts:
for key, value in dictionary.items():
try:
new[key].append(value)
except KeyError:
new[key] = [value]
O/P -
{'a': ['2', '3.4', 1.2], 'c': ['t', '7.6', 3.4], 'b': ['4'], 'd': ['2.3']}
You can try dict-comprehension and list-comprehension :
new_dict = {k : [j[k] for j in [one,two,three] if k in j] for k in set(list(one.keys())+list(two.keys())+list(three.keys())
# Output : { 'a': ['2', '3.4', 1.2], 'b': ['4'], 'c': ['t', '7.6', 3.4], 'd': ['2.3']}
If you want the keys with only one element as possible value not in the list then try this :
new_dict = a = {k : [j[k] for j in [one,two,three] if k in j][0] if len([j[k] for j in [one,two,three] if k in j]) ==1 else [j[k] for j in [one,two,three] if k in j] for k in set(list(one.keys())+list(two.keys())+list(three.keys()))}
# Output : {'a': ['2', '3.4', 1.2], 'b': '4', 'c': ['t', '7.6', 3.4], 'd': '2.3'}