edward
edward

Reputation: 29

How to determine how many times an element is present in a list?

I have python list like below

x = [False, 44, 3, 56, 3, [33, 45, 66, 3], ('c', 3), [4, 3]]*4

I want to count '3' , how many time its in this list, I have tried with for loop but it not count in side the another list and tuple, How to do it ?

expected output is 20.

Upvotes: 0

Views: 996

Answers (7)

Alain T.
Alain T.

Reputation: 42143

You should probably check for types list and tuple specifically. Otherwise you won't properly count strings in the multi-level list.

here's a small recursive function that will do it:

x = [False, 44, 3, 56, 3, [33, 45, 66, 3], ('c', 3), [4, 3]]*4

def deepcount(value,target):
    if not isinstance(value,(list,tuple)):
        return int(value==target)
    return sum(deepcount(v,target) for v in value)

print(deepcount(x,3)) # 20

it will properly count strings in the structure:

y = ["abc", 12, "a",[23, False,"abc"]]*3

print(deepcount(y,"abc")) # 6
print(deepcount(y,"a"))   # 3

Upvotes: 0

C.Nivs
C.Nivs

Reputation: 13106

You can check if an object is iterable by using the hasattr(obj, '__iter__') call

x = [False, 44, 3, 56, 3, [33, 45, 66, 3], ('c', 3), [4, 3]]*4

threes = 0

for item in x:
    # object is iterable, iterate over it
    if hasattr(item '__iter__'):
        for sub_item in item:
            if sub_item==3:
                threes +=1
    # otherwise it isn't, go ahead and do an equality check
    elif item==3:
        threes +=1

threes
20

To make this a recursive solution similar to others that are posted, be wary of hasattr(obj, '__iter__'), as for str types this will lead to infinite recursion. To avoid this:

def count_threes(x):
    count = 0
    for item in x:
        if isinstance(item, str) or isinstance(item, bytes):
            continue # skip to avoid infinite recursion
        if hasattr(item, '__iter__'): # is an iterable
            count += count_threes(item)
        elif item == 3:
            count += 1
    return count

count_threes(x)
20

Upvotes: 0

Sheldore
Sheldore

Reputation: 39042

You can first flatten your irregular list using this method and then apply count(3)

from collections import Iterable, Counter

x = [False, 44, 3, 56, 3, [33, 45, 66, 3], ('c', 3), [4, 3]]*4

def flatten(l):
    for el in l:
        if isinstance(el, Iterable) and not isinstance(el, (str, bytes)):
            yield from flatten(el)
        else:
            yield el

freqs = list(flatten(x)).count(3)            

# 20

For reasons pointed out again by @bhlsing below, you can just iterate through the list ad count the occurrences of 3 and sum

sum(1 for i in flatten(x) if i == 3)

Alternatively You can also use Counter if you want the frequency of all elements. For a single element, this would be an overkill as pointed out by @bhlsing

freqs = Counter(flatten(x))
print (freqs[3])

Upvotes: 3

Mateusz Pełechaty
Mateusz Pełechaty

Reputation: 161

In this solution, you just check every list and search for 3 in it

x = [False, 44, 3, 56, 3, [33, 45, 66, 3], ('c', 3), [4, 3]]*4
counter = 0
stash = []
stash.append(x)
while len(stash)!=0:
    print(stash)
    list = stash[0]
    for element in list:
        if hasattr(element, '__iter__') and not isinstance(element, str):
            stash.append(element)
        if element == 3:
            counter += 1
    stash.remove(list)
print(counter)

`

Upvotes: 0

Booboo
Booboo

Reputation: 44043

One of many ways:

def flatten(*args):
    for x in args:
        if isinstance(x, (list, tuple)):
            for y in flatten(*x):
                yield y
        else:
            yield x

x = [False, 44, 3, 56, 3, [33, 45, 66, 3], ('c', 3), [4, 3]]*4

print(len(list(filter(lambda x: x == 3, flatten(x)))))  

Upvotes: 0

Olvin Roght
Olvin Roght

Reputation: 7812

Function:

def count_element(obj, el):
    occurences = 0
    for item in obj:
        if isinstance(item, (list, tuple, set)):
            occurences += count_element(item, el)
        elif isinstance(item, type(el)):
            occurences += int(item == el)
    return occurences

Usage:

x = [False, 44, 3, 56, 3, [33, 45, 66, 3], ('c', 3), [4, 3]] * 4
count = count_element(x, 3)

Output:

20

Upvotes: 0

Green Cloak Guy
Green Cloak Guy

Reputation: 24691

Slow, hacky implementation of recursive count:

def recursive_count(lst, item):
    count = 0
        for elem in lst:
            if elem == item:
                count += 1
            elif type(elem) in (list, dict, set, tuple):  # or something else to check for iterale types
                count += recursive_count(elem, item)
    return count

Upvotes: 0

Related Questions