4

This is probably quite a straightforward question, but I can't find an answer elsewhere so I'll ask. What is the best way to find the number of times an element appears in a nested list? For example:

my_list=[[a,b,c,d],[a,b,z,d],[a,c,f,e],[d,w,f,a]]

How would I find how many times 'a' is the first element of the list? Or more generally, how many times 'a' appears in my_list at all? I imagine there's a way to do this with collections.Counter, but I haven't been able to figure it out.

EDIT For my_list, I would like an output of a:3 when counting if it's the first element of the list. If the question was changed to see if b is the second element, the desired output would be b:2

Cœur
  • 37,241
  • 25
  • 195
  • 267
Snaaa
  • 256
  • 1
  • 3
  • 14
  • possible duplicate of [Nested List and count()](http://stackoverflow.com/questions/5828123/nested-list-and-count) – Björn Pollex Aug 06 '12 at 13:44
  • not an intentional duplicate! I'm more interested in counting from a specific place in the list (i.e. first element) too, not just generally in the list – Snaaa Aug 06 '12 at 13:50
  • 1
    In this case your question is not very clear. If you provide an example, you should also provide the expected output. Also, the question I have linked certainly contains enough suggestions that you might come up with a solution yourself. This is very symptomatic for the Python-tag. There are a lot of very similar questions about *how to do x with a [nested] list?* - the answer is probably already there. – Björn Pollex Aug 06 '12 at 13:57
  • 4
    Please understand that I do not want to discourage you from asking questions - I want to encourage you to do more research before you do. If the material you found does not quite solve your problem, link to it in your question, so that others can see what you have so far. – Björn Pollex Aug 06 '12 at 13:59
  • Thank you for the feedback, I'll try and make my questions clearer in future :) If I can find the previous questions I've looked at, I'll add some links in – Snaaa Aug 06 '12 at 14:01

3 Answers3

12

Use a nested generator expression:

Counter(x for sublist in my_list for x in sublist)

To count the items in the first position, a different generator expression gets that item for counting:

Counter(sublist[0] for sublist in my_list)

Demo:

>>> from collections import Counter
>>> my_list=[['a','b','c','d'],['a','b','z','d'],['a','c','f','e'],['d','w','f','a']]
>>> Counter(x for sublist in my_list for x in sublist)
Counter({'a': 4, 'd': 3, 'c': 2, 'b': 2, 'f': 2, 'e': 1, 'w': 1, 'z': 1})
>>> Counter(sublist[0] for sublist in my_list)
Counter({'a': 3, 'd': 1})
Martijn Pieters
  • 1,048,767
  • 296
  • 4,058
  • 3,343
3
from collections import Counter
from itertools import chain

counts = Counter(chain.from_iterable(my_list))

or generate a new list and use count:

new_list = list(chain.from_iterable(my_list))
print new_list.count(whatever)

If you wanted how many times 'a' is the first, then something like:

sum(1 for el in my_list if el[0] is a) # or == a if object identity is not required
Jon Clements
  • 138,671
  • 33
  • 247
  • 280
1
>>> from collections import defaultdict, Counter
>>> my_list = [['a', 'b', 'c', 'd'], ['a', 'b', 'z', 'd'], ['a', 'c', 'f', 'e'], ['d', 'w', 'f', 'a']]
>>> pos_count = defaultdict(Counter)
>>> for sublist in my_list:
        for i, c in enumerate(sublist):
            pos_count[c][i] += 1


>>> pos_count['a'][0]
3
>>> pos_count['b'][1]
2
jamylak
  • 128,818
  • 30
  • 231
  • 230
  • there is a lot of overhead in this, is there a procedural way to do this efficiently? where the work is only done as the user/code requests it to be done? – Inbar Rose Aug 06 '12 at 14:07
  • 1
    @InbarRose Is the overhead really a problem? I was thinking about the growth, this will be more efficient for frequent/many accesses once it has been initialized. Go with the approach by MartijnPieters in this case then although I'm still not sure if that's actually a problem :D – jamylak Aug 06 '12 at 14:11