Creating Python defaultdict using nested list of tuples
The scenario is that I have a 2-D list. Each item of the inner list is tuple (key, value pair). The key might repeat in the list. I want to create a default-dict on the fly, in such a way that finally, the dictionary stores the key, and the cumulative sum of all the values of that key from the 2-D list.
To put the code :
listOfItems = [[('a', 1), ('b', 3)], [('a', 6)], [('c', 0), ('d', 5), ('b', 2)]]
finalDict = defaultdict(int)
for eachItem in listOfItems:
for key, val in eachItem:
finalDict[key] += val
print(finalDict)
This is giving me what I want : defaultdict(<class 'int'>, 'a': 7, 'b': 5, 'c': 0, 'd': 5)
but I am looking for a more 'Pythonic' way using comprehensions. So I tried the below :
finalDict = defaultdict(int)
finalDict = key : finalDict[key]+val for eachItem in listOfItems for key, val in eachItem
print(finalDict)
But the output is : 'a': 6, 'b': 2, 'c': 0, 'd': 5
What is it that I am doing wrong? Or is it that when using comprehension the Dictionary is not created and modified on the fly?
python python-3.x nested-lists defaultdict dictionary-comprehension
add a comment |
The scenario is that I have a 2-D list. Each item of the inner list is tuple (key, value pair). The key might repeat in the list. I want to create a default-dict on the fly, in such a way that finally, the dictionary stores the key, and the cumulative sum of all the values of that key from the 2-D list.
To put the code :
listOfItems = [[('a', 1), ('b', 3)], [('a', 6)], [('c', 0), ('d', 5), ('b', 2)]]
finalDict = defaultdict(int)
for eachItem in listOfItems:
for key, val in eachItem:
finalDict[key] += val
print(finalDict)
This is giving me what I want : defaultdict(<class 'int'>, 'a': 7, 'b': 5, 'c': 0, 'd': 5)
but I am looking for a more 'Pythonic' way using comprehensions. So I tried the below :
finalDict = defaultdict(int)
finalDict = key : finalDict[key]+val for eachItem in listOfItems for key, val in eachItem
print(finalDict)
But the output is : 'a': 6, 'b': 2, 'c': 0, 'd': 5
What is it that I am doing wrong? Or is it that when using comprehension the Dictionary is not created and modified on the fly?
python python-3.x nested-lists defaultdict dictionary-comprehension
add a comment |
The scenario is that I have a 2-D list. Each item of the inner list is tuple (key, value pair). The key might repeat in the list. I want to create a default-dict on the fly, in such a way that finally, the dictionary stores the key, and the cumulative sum of all the values of that key from the 2-D list.
To put the code :
listOfItems = [[('a', 1), ('b', 3)], [('a', 6)], [('c', 0), ('d', 5), ('b', 2)]]
finalDict = defaultdict(int)
for eachItem in listOfItems:
for key, val in eachItem:
finalDict[key] += val
print(finalDict)
This is giving me what I want : defaultdict(<class 'int'>, 'a': 7, 'b': 5, 'c': 0, 'd': 5)
but I am looking for a more 'Pythonic' way using comprehensions. So I tried the below :
finalDict = defaultdict(int)
finalDict = key : finalDict[key]+val for eachItem in listOfItems for key, val in eachItem
print(finalDict)
But the output is : 'a': 6, 'b': 2, 'c': 0, 'd': 5
What is it that I am doing wrong? Or is it that when using comprehension the Dictionary is not created and modified on the fly?
python python-3.x nested-lists defaultdict dictionary-comprehension
The scenario is that I have a 2-D list. Each item of the inner list is tuple (key, value pair). The key might repeat in the list. I want to create a default-dict on the fly, in such a way that finally, the dictionary stores the key, and the cumulative sum of all the values of that key from the 2-D list.
To put the code :
listOfItems = [[('a', 1), ('b', 3)], [('a', 6)], [('c', 0), ('d', 5), ('b', 2)]]
finalDict = defaultdict(int)
for eachItem in listOfItems:
for key, val in eachItem:
finalDict[key] += val
print(finalDict)
This is giving me what I want : defaultdict(<class 'int'>, 'a': 7, 'b': 5, 'c': 0, 'd': 5)
but I am looking for a more 'Pythonic' way using comprehensions. So I tried the below :
finalDict = defaultdict(int)
finalDict = key : finalDict[key]+val for eachItem in listOfItems for key, val in eachItem
print(finalDict)
But the output is : 'a': 6, 'b': 2, 'c': 0, 'd': 5
What is it that I am doing wrong? Or is it that when using comprehension the Dictionary is not created and modified on the fly?
python python-3.x nested-lists defaultdict dictionary-comprehension
python python-3.x nested-lists defaultdict dictionary-comprehension
asked Nov 13 '18 at 14:56
PrincePrince
738
738
add a comment |
add a comment |
4 Answers
4
active
oldest
votes
Yes a comprehension can't be updated on-the-fly. Anyway, this task might be better suited to collections.Counter()
with .update()
calls:
>>> from collections import Counter
>>> c = Counter()
>>> for eachItem in listOfItems:
... c.update(dict(eachItem))
...
>>> c
Counter('a': 7, 'b': 5, 'd': 5, 'c': 0)
Ok.. I should have mentioned, the values in the list can be float too. I missed that point trying to simplify my question. Any way to handle that @Chris_Rands? Thanks for help..!
– Prince
Nov 13 '18 at 17:48
add a comment |
This is because you do not assign any value to your finalDict inside your dict in comprehension.
In your dict in comprehension you are literally changing the type of finalDict
As far as I know you cannot assign value to your dict inside a dict in comprehension.
Here is a way to get the dictionnary you want
from functools import reduce
listOfItems = [[('a', 1), ('b', 3)], [('a', 6)], [('c', 0), ('d', 5), ('b', 2)]]
list_dict = [key: val for eachItem in listOfItems for key, val in eachItem]
def sum_dict(x, y):
return k: x.get(k, 0) + y.get(k, 0) for k in set(x)
print(reduce(sum_dict, list_dict))
add a comment |
Simple solution without using additional modules:
inp_list = [[('a', 1), ('b', 3)], [('a', 6)], [('c', 0), ('d', 5), ('b', 2)]]
l = [item for sublist in inp_list for item in sublist] # flatten the list
sums = [(key, sum([b for (a,b) in l if a == key])) for key in dict(l)]
print(sums)
1
notice you can use itertools.chain(*inp_list) to flatten the list
– Aaron_ab
Dec 9 '18 at 13:07
add a comment |
trying to use python's built-in methods instead of coding the functionality myself:
The long and explained solution
from itertools import chain, groupby
from operator import itemgetter
listOfItems = [[('a', 1), ('b', 3)], [('a', 6)], [('c', 0), ('d', 5), ('b', 2)]]
# just flat the list of lists into 1 list..
flatten_list = chain(*listOfItems)
# get all elements grouped by the key, e.g 'a', 'b' etc..
first = itemgetter(0)
groupedByKey = groupby(sorted(flatten_list, key=first), key=first))
#sum
summed_by_key = ((k, sum(item[1] for item in tups_to_sum)) for k, tups_to_sum in groupedByKey)
# create a dict
d = dict(summed_by_key)
print(d) # 'a': 7, 'b': 5, 'c': 0, 'd': 5
~one line solution
from itertools import chain, groupby
from operator import itemgetter
first = itemgetter(0)
d = dict((k, sum(item[1] for item in tups_to_sum)) for k, tups_to_sum in groupby(sorted(chain(*listOfItems), key=first), key=first))
print(d) # 'a': 7, 'b': 5, 'c': 0, 'd': 5
add a comment |
Your Answer
StackExchange.ifUsing("editor", function ()
StackExchange.using("externalEditor", function ()
StackExchange.using("snippets", function ()
StackExchange.snippets.init();
);
);
, "code-snippets");
StackExchange.ready(function()
var channelOptions =
tags: "".split(" "),
id: "1"
;
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function()
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled)
StackExchange.using("snippets", function()
createEditor();
);
else
createEditor();
);
function createEditor()
StackExchange.prepareEditor(
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader:
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
,
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
);
);
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53283759%2fcreating-python-defaultdict-using-nested-list-of-tuples%23new-answer', 'question_page');
);
Post as a guest
Required, but never shown
4 Answers
4
active
oldest
votes
4 Answers
4
active
oldest
votes
active
oldest
votes
active
oldest
votes
Yes a comprehension can't be updated on-the-fly. Anyway, this task might be better suited to collections.Counter()
with .update()
calls:
>>> from collections import Counter
>>> c = Counter()
>>> for eachItem in listOfItems:
... c.update(dict(eachItem))
...
>>> c
Counter('a': 7, 'b': 5, 'd': 5, 'c': 0)
Ok.. I should have mentioned, the values in the list can be float too. I missed that point trying to simplify my question. Any way to handle that @Chris_Rands? Thanks for help..!
– Prince
Nov 13 '18 at 17:48
add a comment |
Yes a comprehension can't be updated on-the-fly. Anyway, this task might be better suited to collections.Counter()
with .update()
calls:
>>> from collections import Counter
>>> c = Counter()
>>> for eachItem in listOfItems:
... c.update(dict(eachItem))
...
>>> c
Counter('a': 7, 'b': 5, 'd': 5, 'c': 0)
Ok.. I should have mentioned, the values in the list can be float too. I missed that point trying to simplify my question. Any way to handle that @Chris_Rands? Thanks for help..!
– Prince
Nov 13 '18 at 17:48
add a comment |
Yes a comprehension can't be updated on-the-fly. Anyway, this task might be better suited to collections.Counter()
with .update()
calls:
>>> from collections import Counter
>>> c = Counter()
>>> for eachItem in listOfItems:
... c.update(dict(eachItem))
...
>>> c
Counter('a': 7, 'b': 5, 'd': 5, 'c': 0)
Yes a comprehension can't be updated on-the-fly. Anyway, this task might be better suited to collections.Counter()
with .update()
calls:
>>> from collections import Counter
>>> c = Counter()
>>> for eachItem in listOfItems:
... c.update(dict(eachItem))
...
>>> c
Counter('a': 7, 'b': 5, 'd': 5, 'c': 0)
edited Nov 13 '18 at 15:20
answered Nov 13 '18 at 15:02
Chris_RandsChris_Rands
16.1k53870
16.1k53870
Ok.. I should have mentioned, the values in the list can be float too. I missed that point trying to simplify my question. Any way to handle that @Chris_Rands? Thanks for help..!
– Prince
Nov 13 '18 at 17:48
add a comment |
Ok.. I should have mentioned, the values in the list can be float too. I missed that point trying to simplify my question. Any way to handle that @Chris_Rands? Thanks for help..!
– Prince
Nov 13 '18 at 17:48
Ok.. I should have mentioned, the values in the list can be float too. I missed that point trying to simplify my question. Any way to handle that @Chris_Rands? Thanks for help..!
– Prince
Nov 13 '18 at 17:48
Ok.. I should have mentioned, the values in the list can be float too. I missed that point trying to simplify my question. Any way to handle that @Chris_Rands? Thanks for help..!
– Prince
Nov 13 '18 at 17:48
add a comment |
This is because you do not assign any value to your finalDict inside your dict in comprehension.
In your dict in comprehension you are literally changing the type of finalDict
As far as I know you cannot assign value to your dict inside a dict in comprehension.
Here is a way to get the dictionnary you want
from functools import reduce
listOfItems = [[('a', 1), ('b', 3)], [('a', 6)], [('c', 0), ('d', 5), ('b', 2)]]
list_dict = [key: val for eachItem in listOfItems for key, val in eachItem]
def sum_dict(x, y):
return k: x.get(k, 0) + y.get(k, 0) for k in set(x)
print(reduce(sum_dict, list_dict))
add a comment |
This is because you do not assign any value to your finalDict inside your dict in comprehension.
In your dict in comprehension you are literally changing the type of finalDict
As far as I know you cannot assign value to your dict inside a dict in comprehension.
Here is a way to get the dictionnary you want
from functools import reduce
listOfItems = [[('a', 1), ('b', 3)], [('a', 6)], [('c', 0), ('d', 5), ('b', 2)]]
list_dict = [key: val for eachItem in listOfItems for key, val in eachItem]
def sum_dict(x, y):
return k: x.get(k, 0) + y.get(k, 0) for k in set(x)
print(reduce(sum_dict, list_dict))
add a comment |
This is because you do not assign any value to your finalDict inside your dict in comprehension.
In your dict in comprehension you are literally changing the type of finalDict
As far as I know you cannot assign value to your dict inside a dict in comprehension.
Here is a way to get the dictionnary you want
from functools import reduce
listOfItems = [[('a', 1), ('b', 3)], [('a', 6)], [('c', 0), ('d', 5), ('b', 2)]]
list_dict = [key: val for eachItem in listOfItems for key, val in eachItem]
def sum_dict(x, y):
return k: x.get(k, 0) + y.get(k, 0) for k in set(x)
print(reduce(sum_dict, list_dict))
This is because you do not assign any value to your finalDict inside your dict in comprehension.
In your dict in comprehension you are literally changing the type of finalDict
As far as I know you cannot assign value to your dict inside a dict in comprehension.
Here is a way to get the dictionnary you want
from functools import reduce
listOfItems = [[('a', 1), ('b', 3)], [('a', 6)], [('c', 0), ('d', 5), ('b', 2)]]
list_dict = [key: val for eachItem in listOfItems for key, val in eachItem]
def sum_dict(x, y):
return k: x.get(k, 0) + y.get(k, 0) for k in set(x)
print(reduce(sum_dict, list_dict))
answered Nov 13 '18 at 15:24
BlueSheepTokenBlueSheepToken
1,348516
1,348516
add a comment |
add a comment |
Simple solution without using additional modules:
inp_list = [[('a', 1), ('b', 3)], [('a', 6)], [('c', 0), ('d', 5), ('b', 2)]]
l = [item for sublist in inp_list for item in sublist] # flatten the list
sums = [(key, sum([b for (a,b) in l if a == key])) for key in dict(l)]
print(sums)
1
notice you can use itertools.chain(*inp_list) to flatten the list
– Aaron_ab
Dec 9 '18 at 13:07
add a comment |
Simple solution without using additional modules:
inp_list = [[('a', 1), ('b', 3)], [('a', 6)], [('c', 0), ('d', 5), ('b', 2)]]
l = [item for sublist in inp_list for item in sublist] # flatten the list
sums = [(key, sum([b for (a,b) in l if a == key])) for key in dict(l)]
print(sums)
1
notice you can use itertools.chain(*inp_list) to flatten the list
– Aaron_ab
Dec 9 '18 at 13:07
add a comment |
Simple solution without using additional modules:
inp_list = [[('a', 1), ('b', 3)], [('a', 6)], [('c', 0), ('d', 5), ('b', 2)]]
l = [item for sublist in inp_list for item in sublist] # flatten the list
sums = [(key, sum([b for (a,b) in l if a == key])) for key in dict(l)]
print(sums)
Simple solution without using additional modules:
inp_list = [[('a', 1), ('b', 3)], [('a', 6)], [('c', 0), ('d', 5), ('b', 2)]]
l = [item for sublist in inp_list for item in sublist] # flatten the list
sums = [(key, sum([b for (a,b) in l if a == key])) for key in dict(l)]
print(sums)
edited Nov 13 '18 at 21:56
answered Nov 13 '18 at 15:18
svfatsvfat
1,055626
1,055626
1
notice you can use itertools.chain(*inp_list) to flatten the list
– Aaron_ab
Dec 9 '18 at 13:07
add a comment |
1
notice you can use itertools.chain(*inp_list) to flatten the list
– Aaron_ab
Dec 9 '18 at 13:07
1
1
notice you can use itertools.chain(*inp_list) to flatten the list
– Aaron_ab
Dec 9 '18 at 13:07
notice you can use itertools.chain(*inp_list) to flatten the list
– Aaron_ab
Dec 9 '18 at 13:07
add a comment |
trying to use python's built-in methods instead of coding the functionality myself:
The long and explained solution
from itertools import chain, groupby
from operator import itemgetter
listOfItems = [[('a', 1), ('b', 3)], [('a', 6)], [('c', 0), ('d', 5), ('b', 2)]]
# just flat the list of lists into 1 list..
flatten_list = chain(*listOfItems)
# get all elements grouped by the key, e.g 'a', 'b' etc..
first = itemgetter(0)
groupedByKey = groupby(sorted(flatten_list, key=first), key=first))
#sum
summed_by_key = ((k, sum(item[1] for item in tups_to_sum)) for k, tups_to_sum in groupedByKey)
# create a dict
d = dict(summed_by_key)
print(d) # 'a': 7, 'b': 5, 'c': 0, 'd': 5
~one line solution
from itertools import chain, groupby
from operator import itemgetter
first = itemgetter(0)
d = dict((k, sum(item[1] for item in tups_to_sum)) for k, tups_to_sum in groupby(sorted(chain(*listOfItems), key=first), key=first))
print(d) # 'a': 7, 'b': 5, 'c': 0, 'd': 5
add a comment |
trying to use python's built-in methods instead of coding the functionality myself:
The long and explained solution
from itertools import chain, groupby
from operator import itemgetter
listOfItems = [[('a', 1), ('b', 3)], [('a', 6)], [('c', 0), ('d', 5), ('b', 2)]]
# just flat the list of lists into 1 list..
flatten_list = chain(*listOfItems)
# get all elements grouped by the key, e.g 'a', 'b' etc..
first = itemgetter(0)
groupedByKey = groupby(sorted(flatten_list, key=first), key=first))
#sum
summed_by_key = ((k, sum(item[1] for item in tups_to_sum)) for k, tups_to_sum in groupedByKey)
# create a dict
d = dict(summed_by_key)
print(d) # 'a': 7, 'b': 5, 'c': 0, 'd': 5
~one line solution
from itertools import chain, groupby
from operator import itemgetter
first = itemgetter(0)
d = dict((k, sum(item[1] for item in tups_to_sum)) for k, tups_to_sum in groupby(sorted(chain(*listOfItems), key=first), key=first))
print(d) # 'a': 7, 'b': 5, 'c': 0, 'd': 5
add a comment |
trying to use python's built-in methods instead of coding the functionality myself:
The long and explained solution
from itertools import chain, groupby
from operator import itemgetter
listOfItems = [[('a', 1), ('b', 3)], [('a', 6)], [('c', 0), ('d', 5), ('b', 2)]]
# just flat the list of lists into 1 list..
flatten_list = chain(*listOfItems)
# get all elements grouped by the key, e.g 'a', 'b' etc..
first = itemgetter(0)
groupedByKey = groupby(sorted(flatten_list, key=first), key=first))
#sum
summed_by_key = ((k, sum(item[1] for item in tups_to_sum)) for k, tups_to_sum in groupedByKey)
# create a dict
d = dict(summed_by_key)
print(d) # 'a': 7, 'b': 5, 'c': 0, 'd': 5
~one line solution
from itertools import chain, groupby
from operator import itemgetter
first = itemgetter(0)
d = dict((k, sum(item[1] for item in tups_to_sum)) for k, tups_to_sum in groupby(sorted(chain(*listOfItems), key=first), key=first))
print(d) # 'a': 7, 'b': 5, 'c': 0, 'd': 5
trying to use python's built-in methods instead of coding the functionality myself:
The long and explained solution
from itertools import chain, groupby
from operator import itemgetter
listOfItems = [[('a', 1), ('b', 3)], [('a', 6)], [('c', 0), ('d', 5), ('b', 2)]]
# just flat the list of lists into 1 list..
flatten_list = chain(*listOfItems)
# get all elements grouped by the key, e.g 'a', 'b' etc..
first = itemgetter(0)
groupedByKey = groupby(sorted(flatten_list, key=first), key=first))
#sum
summed_by_key = ((k, sum(item[1] for item in tups_to_sum)) for k, tups_to_sum in groupedByKey)
# create a dict
d = dict(summed_by_key)
print(d) # 'a': 7, 'b': 5, 'c': 0, 'd': 5
~one line solution
from itertools import chain, groupby
from operator import itemgetter
first = itemgetter(0)
d = dict((k, sum(item[1] for item in tups_to_sum)) for k, tups_to_sum in groupby(sorted(chain(*listOfItems), key=first), key=first))
print(d) # 'a': 7, 'b': 5, 'c': 0, 'd': 5
answered Dec 9 '18 at 13:07
Aaron_abAaron_ab
1,013723
1,013723
add a comment |
add a comment |
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53283759%2fcreating-python-defaultdict-using-nested-list-of-tuples%23new-answer', 'question_page');
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown