0

Just went through list, dictionary, set comprehensions and understood lambda expressions but I'm unable to use them to capture the number of occurrences of integers in a nested list as illustrated in the example below. So, is there a solution with comprehensions or lambda expressions to compute it or is it beyond the capability of such constructs? If it's not possible, then what's the intuition for why it cannot be achieved with comprehensions/lambda expressions?

lst = [[0,1],[1,2],[3,4],[0,5]]
result = {0:2, 1:2, 2:1, 3:1, 4:1, 5:1}

I'm currently using a double for loop to do the computation.

Patrick Artner
  • 50,409
  • 9
  • 43
  • 69
aak318
  • 158
  • 1
  • 10
  • In what way are you "unable to use [lambda expressions]" for this? Can you show us what you tried? – mypetlion Dec 20 '18 at 17:31
  • for instance, using `map(lambda x:sum(x), lst)` which come close but not quite what I am looking for. – aak318 Dec 21 '18 at 03:16

4 Answers4

2

The constructs of generator expressions, list comprehensions, etc. are good for individually mapping the items in a sequence. They are not at all meant for aggregation, which is what you are trying to do here, i.e. combining the values of several items.

For your purpose you can use the collections.Counter (which does the aggregation of counting items) with a generator expression that flattens the nested lists instead:

from collections import Counter
dict(Counter(i for s in lst for i in s))

This returns:

{0: 2, 1: 2, 2: 1, 3: 1, 4: 1, 5: 1}
blhsing
  • 91,368
  • 6
  • 71
  • 106
1

You can utilize itertools.chain and the Counter object to get these results.

from itertools import chain
from collections import Counter

result = Counter(chain(*lst))

Calling chain will flatten your lists and Counter will provide the frequency counts of each value in the flattened list.

vielkind
  • 2,840
  • 1
  • 16
  • 16
0

You can flatten your nested lists to get a single list using sum and then apply Counter to get the frequency of occurrence of each element

from collections import Counter

lst = [[0,1],[1,2],[3,4],[0,5]]
flat = sum(lst, [])
print (flat)
# [0, 1, 1, 2, 3, 4, 0, 5]

Counter(flat)

# Counter({0: 2, 1: 2, 2: 1, 3: 1, 4: 1, 5: 1})
Sheldore
  • 37,862
  • 7
  • 57
  • 71
  • Thanks for showing how to flatten the list in one line but I'm curious as to how it works. – aak318 Dec 23 '18 at 12:01
  • It simply maps the sum function to individual sublists. So `[]` tells it to sum all the objects of type `[]` (list). In python if you have two lists `a=[1,2,3]` and `b = [4,5,6]` then `a+b` becomes `[1,2,3,4,5,6]` – Sheldore Dec 23 '18 at 13:18
  • So, it doesn't work for arbitrarily nested lists of integers. – aak318 Dec 23 '18 at 16:15
  • @aak318: It will work for any arbitrary nested list. For example, [1,2,3] and [4,5] and [6] will work too to get [1,2,3,4,5,6] – Sheldore Dec 23 '18 at 16:16
  • No by arbitrary nesting, I meant for example `lst=[[0,1],[[2],[3]],[5]]` and the like. – aak318 Dec 23 '18 at 16:20
  • Oh I see. It won't work for such case. I mean it will still work as it should giving `[0, 1, [2], [3], 5]` as the output. The sublist depth is only 1 in this case – Sheldore Dec 23 '18 at 16:22
  • @aak318: For your arbitrary list question, [this](https://stackoverflow.com/questions/2158395/flatten-an-irregular-list-of-lists) is the best post to follow – Sheldore Dec 23 '18 at 16:23
  • thanks for that post on flattening as I might need it later. – aak318 Dec 25 '18 at 04:16
0

You could count each element in the sub-lists (using Counter) and sum the counts:

from collections import Counter

lst = [[0, 1], [1, 2], [3, 4], [0, 5]]

result = sum(map(Counter, lst), Counter())
print(result)

Output

Counter({0: 2, 1: 2, 2: 1, 3: 1, 4: 1, 5: 1})
Dani Mesejo
  • 61,499
  • 6
  • 49
  • 76