Related
This question already has answers here:
How do I initialize a dictionary of empty lists in Python?
(7 answers)
Closed last month.
here's my code:
import copy
teamdict = {1:{},2:{},3:{},4:{},5:{}}
teamlst = []
matchlst = [1,2,3,4,5]
lst = [[1,5,0],[1,0,3],[2,3,0],[2,0,1],[3,0,6],[3,0,1],[4,0,1],[4,0,5],[5,0,8]]
for i in matchlst:
for j in lst:
if i == j[0]:
teamlst.append(j[2])
elif len(teamlst)>0 and i != j:
continue
else:
pass
teamlst = set(teamlst)
teamlst = list(teamlst)
teamlst.sort()
team_dictionary = dict.fromkeys(teamlst, [])
teamdict[i] = team_dictionary
teamlst.clear()
print(teamdict)
dic = copy.deepcopy(teamdict)
for i in lst:
dic[i[0]][i[2]].append(i[1])
print(dic)
this is what i got:
{1: {0: [5, 0], 3: [5, 0]}, 2: {0: [3, 0], 1: [3, 0]}, 3: {1: [0, 0], 6: [0, 0]}, 4: {1: [0, 0], 5: [0, 0]}, 5: {8: [0]}}
but what i expect is:
{1: {0: [5], 3: [0]}, 2: {0: [3], 1: [0]}, 3: {1: [0], 6: [0]}, 4: {1: [0], 5: [0]}, 5: {8: [0]}}
what goes wrong?
seems like this append method add the element to all the keys in the nested dictionary
I assume you have created your dictionary with multiple references to the same list.
If I execute your code I get what you want.
>>> lst = [[1,5,0],[1,0,3],[2,3,0],[2,0,1],[3,0,6],[3,0,1],[4,0,1],[4,0,5],[5,0,8]]
>>> dic = {1: {0: [], 3: []}, 2: {0: [], 1: []}, 3: {1: [], 6: []}, 4: {1: [], 5: []}, 5: {8: []}}
>>> for i in lst:
... dic[i[0]][i[2]].append(i[1])
...
>>> print(dic)
{1: {0: [5], 3: [0]}, 2: {0: [3], 1: [0]}, 3: {1: [0], 6: [0]}, 4: {1: [0], 5: [0]}, 5: {8: [0]}}
I have a large list, which I separated into small sized lists which have elements of occurrences of 1s and 0s, randomly.
Also, the first two lists are made with different parameters from the last two.
Example:
list_of_lists[0] =[1,0,1,1,1,0,1,1,1,0]
list_of_lists[1] =[0,0,0,0,0,0,0,0,0,0]
list_of_lists[2] =[1,1,1,1,1,1,1,1,1,1]
list_of_lists[3] =[0,0,1,1,1,1,1,1,1,0]
I would like to count the occurrences of 1s and 0s in each list, and append them into a dictionary to plot the occurrences.
My trial is as follows:
counts_each = dict()
for i in range(4): #all 4 lists
for k in list_of_lists[i]: #elements of the lists
counts_each[k] = counts_each.get(k, 0) + 1
print(counts_each)
which calculates the general occurrences of the 1s and 0s for the al lists:
{0: 16, 1: 24}
If I do:
list_counts = []
for i in range(4):
counts_each = dict()
for k in list_of_lists[i]:
counts_each[k] = counts_each.get(k, 0) + 1
list_counts.append(counts_each)
print(list_counts)
It does not accumulate all of the counts:
[{0: 3, 1: 7},
{0: 3, 1: 7},
{0: 3, 1: 7},
{0: 3, 1: 7},
{0: 3, 1: 7},
{0: 3, 1: 7},
{0: 3, 1: 7},
{0: 3, 1: 7},
{0: 3, 1: 7},
{0: 3, 1: 7},
{0: 10},
{0: 10},
{0: 10},
{0: 10},
{0: 10},
{0: 10},
{0: 10},
{0: 10},
{0: 10},
{0: 10},
{1: 10},
{1: 10},
{1: 10},
{1: 10},
{1: 10},
{1: 10},
{1: 10},
{1: 10},
{1: 10},
{1: 10},
{0: 3, 1: 7},
{0: 3, 1: 7},
{0: 3, 1: 7},
{0: 3, 1: 7},
{0: 3, 1: 7},
{0: 3, 1: 7},
{0: 3, 1: 7},
{0: 3, 1: 7},
{0: 3, 1: 7},
{0: 3, 1: 7}]
I would be glad to have some insights of what I am doing wrong.
Thank you.
You can let the collections module do all the counting work for you.
from collections import Counter
list_of_lists = [[] for _ in range(4)]
list_of_lists[0] =[1,0,1,1,1,0,1,1,1,0]
list_of_lists[1] =[0,0,0,0,0,0,0,0,0,0]
list_of_lists[2] =[1,1,1,1,1,1,1,1,1,1]
list_of_lists[3] =[0,0,1,1,1,1,1,1,1,0]
counters = [Counter(l) for l in list_of_lists]
print(*counters, sep="\n")
OUTPUT
Counter({1: 7, 0: 3})
Counter({0: 10})
Counter({1: 10})
Counter({1: 7, 0: 3})
You could use a Dict Comprehension, given your nested list:
list_of_lists = [[1,0,1,1,1,0,1,1,1,0], [0,0,0,0,0,0,0,0,0,0], [1,1,1,1,1,1,1,1,1,1], [0,0,1,1,1,1,1,1,1,0]]
use it in this way:
{ idx: {0: lst.count(0), 1: lst.count(1)} for idx, lst in enumerate(list_of_lists) }
#=> {0: {0: 3, 1: 7}, 1: {0: 10, 1: 0}, 2: {0: 0, 1: 10}, 3: {0: 3, 1: 7}}
In the above case I used the index as a key, but you could just use a list comprehension to get a list of dictionaries:
[ {0: lst.count(0), 1: lst.count(1)} for lst in list_of_lists ]
#=> [{0: 3, 1: 7}, {0: 10, 1: 0}, {0: 0, 1: 10}, {0: 3, 1: 7}]
Chris Doyle's answer is excellent, but perhaps your goal is to understand the problem with your solution, specifically.
You have not included your expected output. If I am correct that your issue with your current solution is the repetition of the counts, and you want an output like this:
[{1: 7, 0: 3}, {0: 10}, {1: 10}, {0: 3, 1: 7}]
Then the issue appears to be with the indenting of the line list_counts.append(counts_each). You are doing this each time through the k loop (looping through the items in the list) when I think you want to do it only after finishing the count for a given list:
list_counts = []
for i in range(4):
counts_each = dict()
for k in list_of_lists[i]:
counts_each[k] = counts_each.get(k, 0) + 1
list_counts.append(counts_each)
print(list_counts)
d = {0: {0: {0: 0, 1: 0},
1: {0: 0,
2: np.array([ 0.02981036])}},
9: {0: {0: 0, 1: 0},
7: {0: 0,
4: np.array([ 0.01502996]),
9: 0},
8: {0: 0,
1: 0},
9: {0: 0, 1: 0}}}
The dictionary is above, what I want to is delete the keys of which the value is 0, and convert the array form to float. The wanted output is:
d = {0: {1: {2: 0.02981036}}, 9: {7: {4: 0.01502996}}}
I tried to use a for loop to delete the "0" items, but always got KeyError: 0. I am a newbie of python, please help me on board. Thanks!!
A recursive solution:
def func(d):
new_d = {} # create a new dict
if any(v != 0 for v in d.values()): # evaluate items if any `v != 0`
for k, v in d.items():
if type(v) == dict:
new_v = func(v)
if new_v: # do not create key if `func(v)` is an empty dict
new_d[k] = new_v
elif v != 0: # convert other non-zero values to float
new_d[k] = float(v) # place try/except here if you expect non-int values
return new_d
>>> func(d)
Out[]: {0: {1: {2: 0.02981036}}, 9: {7: {4: 0.01502996}}}
What you have here is dict or dict of dict. Using json may be a good idea. But here is a scratch version of solution.
Also, since you are trying to delete keys while iterating through the keys at various levels, you may run into RuntimError issue. For that purpose we will need to deepcopy the dict , iterate through original and delete from the copy.
SourceCode
import numpy as np
import copy
d = {0: {0: {0: 0, 1: 0},
1: {0: 0,
2: np.array([ 0.02981036])}},
9: {0: {0: 0, 1: 0},
7: {0: 0,
4: np.array([ 0.01502996]),
9: 0},
8: {0: 0,
1: 0},
9: {0: 0, 1: 0}}}
d2 = copy.deepcopy(d)
for k1,v1 in d.iteritems():
for k2,v2 in v1.iteritems():
for k3,v3 in v2.iteritems():
#print k1,k2,k3,v3
if v3 == 0:
d2[k1][k2].pop(k3)
if type(v3) is np.ndarray:
v3 = v3.tolist()
d2[k1][k2][k3] = float(''.join(str(i) for i in v3))
if len(d2[k1][k2]) == 0:
d2[k1].pop(k2)
>>> d2
{0: {1: {2: 0.02981036}}, 9: {7: {4: 0.01502996}}}
import numpy
def clean(d):
new = {}
for k, v in d.items():
if v == 0:
pass
elif isinstance(v, numpy.ndarray):
new_element = float(v[0])
new[k] = new_element
else:
new_element = clean(v)
if new_element != {}:
new[k] = new_element
return new
https://repl.it/MO9A/1
You can try this to remove all zeros which have value 0:
import numpy as np
from copy import deepcopy
d = {0: {0: {0: 0, 1: 0},
1: {0: 0,
2: np.array([ 0.02981036])}},
9: {0: {0: 0, 1: 0},
7: {0: 0,
4: np.array([ 0.01502996]),
9: 0},
8: {0: 0,
1: 0},
9: {0: 0, 1: 0}}}
deep_copy=deepcopy(d)
for key,value in d.items():
for key1,value1 in value.items():
for key2,value2 in value1.items():
if value2==0:
del deep_copy[key][key1][key2]
new_deep_copy=deepcopy(deep_copy)
for key,value in deep_copy.items():
for key1,value1 in value.items():
for key2,value2 in value1.items():
if isinstance(value2,np.ndarray):
new_deep_copy[key][key1][key2]=float(value2)
if value1=={}:
del new_deep_copy[key][key1]
print(new_deep_copy)
output:
{0: {1: {2: 36.0}}, 9: {7: {4: 0.01502996}}}
q = "cats dogs"
d = {'cats': {1: 1, 2: 3, 3: 1, 4: 1}, 'nuts': {3: 1}, 'egg': {5: 1, 6: 2}, 'dogs': {1: 8, 2: 2, 3: 4}, 'idea': {4: 1}, 'frog': {2: 1, 4: 1, 5: 1}}
newList = []
for word in q:
for x,y in d.values():
newList.append(d[word].x())
What I'm attempting to do here is get each first part of the number pairs and put into the list when it corresponds to a word in q. So I'm expecting newList to be [1,2,3,4,1,2,3].
I am getting ValueError: too many values to unpack (expected 2). How should I be doing this?
The values in the dictionary 'd' are actually of type dictionary themselves, not tuples. I think you may want to reorganize this a bit.
for word in q.split(" "):
if word in d:
child_dict = d[word]
for key in child_dict:
newList.append(key)
Is this what you're looking for?
q = "cats dogs"
d = {'cats': {1: 1, 2: 3, 3: 1, 4: 1}, 'nuts': {3: 1}, 'egg': {5: 1, 6: 2}, 'dogs': {1: 8, 2: 2, 3: 4}, 'idea': {4: 1}, 'frog': {2: 1, 4: 1, 5: 1}}
newList = []
for word in q.split(' '):
newList.extend(list(d[word].keys()))
print(newList)
It prints out [1, 2, 3, 4, 1, 2, 3]
q = "cats dogs"
d = {'cats': {1: 1, 2: 3, 3: 1, 4: 1}, 'nuts': {3: 1}, 'egg': {5: 1, 6: 2}, 'dogs': {1: 8, 2: 2, 3: 4}, 'idea': {4: 1}, 'frog': {2: 1, 4: 1, 5: 1}}
newList = []
for word in q.split(' '):
if word in d:
newList.extend([i for i in d[word]])
print(newList)
I have two dictionaries, and what I'm trying to do is a bit odd. Basically, I want to merge them. That's simple enough. But they're hierarchies of of dictionaries, and I want to merge them in such a way that if an item in a dictionary is itself a dictionary and exists in both, I want to merge those dictionaries as well. If it's not a dictionary, I want the values from the second dictionary to overwrite the values from the first one. Something sort of like this:
a = {0: {0: "a"},
1: [0, 1, 2]}
b = {0: {1: "b"},
1: [3, 4, 5]}
Merge(a, b)
#output:
{0: {0: "a",
1: "b"},
1: [3, 4, 5]}
Does that make sense? Because the key "0" contained a dictionary in both a and b, it merged those dictionaries as well. But in the case of the second key, it was a list so it just overwrote it.
So I suppose I'll be looking at some kind of recursive function? Not quite sure how to approach this one.
Thanks!
Edit: I forgot to mention one pretty crucial detail:
I need a function that works in both 2.6.2 and 2.7.3.
Assuming you might have nested dictionaries (based on your thinking in terms of recursion), something like this should work,
from copy import deepcopy
def merge(a, b):
if isinstance(b, dict) and isinstance(a, dict):
a_and_b = a.viewkeys() & b.viewkeys()
every_key = a.viewkeys() | b.viewkeys()
return {k: merge(a[k], b[k]) if k in a_and_b else
deepcopy(a[k] if k in a else b[k]) for k in every_key}
return deepcopy(b)
The return value of merge(a, b) is conceptually like creating a (deep) copy of a and running a recursive version of a.update(b).
Using some nested examples,
a = {0: {0: 'a'},
1: [0, 1, 2],
2: [9, 9],
3: {'a': {1: 1, 2: 2}, 'b': [0, 1]}}
b = {0: {1: 'b'},
1: [3, 4, 5],
2: {22: 22, 33: 33},
3: {'a': {2: 22, 3: 33}, 'b': [99, 88]}}
merge(a, b) produces,
{0: {0: 'a', 1: 'b'},
1: [3, 4, 5],
2: {22: 22, 33: 33},
3: {'a': {1: 1, 2: 22, 3: 33}, 'b': [99, 88]}}
EDIT: Python 2.6 version
def merge(a, b):
if isinstance(b, dict) and isinstance(a, dict):
a_and_b = set(a).intersection(b)
every_key = set(a).union(b)
return dict((k, merge(a[k], b[k]) if k in a_and_b else
deepcopy(a[k] if k in a else b[k])) for k in every_key)
return deepcopy(b)
Hmm.. as long as you're not arbitrarily-nested, you don't need recursion.
from itertools import chain
{k:(v if not isinstance(v,dict) else dict(chain(a[k].items(), v.items()))) for k,v in b.items()}
Out[10]: {0: {0: 'a', 1: 'b'}, 1: [3, 4, 5]}
(I'm using python 3 here, feel free to replace .items with .iteritems in python 2)
Since this is a bit verbose, there's always the sneaky way to merge two dicts:
{k:(v if not isinstance(v,dict) else dict(a[k], **v)) for k,v in b.items()}
Out[11]: {0: {0: 'a', 1: 'b'}, 1: [3, 4, 5]}
You may or may not want to use this syntax - though it is compact, it kind of abuses cPython implementation details.
Needed something similar and implemented a more straightforward recursive solution. In-place updates dict 'd'.
from Collections import MutableMapping
def merge(d, v):
"""
Merge two dictionaries.
Merge dict-like `v` into dict-like `d`. In case keys between them are the same, merge
their sub-dictionaries where possible. Otherwise, values in `v` overwrite `d`.
"""
for key in v:
if key in d and isinstance(d[key], MutableMapping) and isinstance(v[key], MutableMapping):
d[key] = merge(d[key], v[key])
else:
d[key] = v[key]
return d
Example 1:
a = {0: {0: "a"},
1: [0, 1, 2]}
b = {0: {1: "b"},
1: [3, 4, 5]}
>>> merge(a, b)
{0: {0: 'a', 1: 'b'}, 1: [3, 4, 5]}
Example 2:
a = {0: {0: 'a'},
1: [0, 1, 2],
2: [9, 9],
3: {'a': {1: 1, 2: 2}, 'b': [0, 1]}}
b = {0: {1: 'b'},
1: [3, 4, 5],
2: {22: 22, 33: 33},
3: {'a': {2: 22, 3: 33}, 'b': [99, 88]}}
>>> merge(a, b)
{0: {0: 'a', 1: 'b'},
1: [3, 4, 5],
2: {22: 22, 33: 33},
3: {'a': {1: 1, 2: 22, 3: 33}, 'b': [99, 88]}}