简体   繁体   中英

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.

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])

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

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

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

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)))))  

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)

`

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM