-2

In short, I am making a function that takes 2 arguments 'sequence' and 'item'. The 'sequence' can be anything - an integer, a string, or a list containing integers or strings. I am trying to make a function that counts the amount of times 'item' occurs in the 'sequence'. Please take into account, I am still a newbie at Python. A simple answer would be very much appreciated. This is what I have so far

def count(sequence, item):
    found = 0
    if sequence == item:
        found += 1
        return found
    else:
        for num in sequence:
            if num == sequence:
                found += 1
                return found
            else:
                return False


print count([4,'foo',5,'hi'], 5)

The else part of the code is meant to be enabled if the sequence is something like a list. I was thinking I should loop through the list using for and do the same thing - but it's not working as it keeps returning False which follows the second 'else' statement. Any idea how I can do this? For clarification, the output in the example above should be 1 because '5' occurs once in the list.

dlmeetei
  • 9,905
  • 3
  • 31
  • 38
arrey
  • 29
  • 2
  • 9
  • What do you want your function to return? If - as the name suggests - you want it to return the count, then *do it*. As it is, your function returns either `False` or `True`, *not* a number. – Błotosmętek Jul 25 '17 at 09:49

5 Answers5

2
len([i for i in sequence if item in i])
Filippos Ser
  • 366
  • 1
  • 6
  • 16
1

EDIT:

Changed return to return the number of occurrences instead of True/False


You are checking each item in sequence and evaluating, if it doesn't equal item it will return False right away, that is why you're getting False always.

You need to have your loop increment found and once the loop is done then use if/else to check whether found == 0 or not. A simple example:

def count(sequence, item):
    found = 0
    if sequence == item:
        return 1

    for num in sequence:
        if num == item:
            found += 1

    return found

If you learned list-comprehension already, you can use it as the following:

def count(sequence, item):
    if sequence == item:
        return 1
    return sum(1 for x in sequence if x == item)
Mohd
  • 5,523
  • 7
  • 19
  • 30
0

If we use your code as a basis, we get the following if we want it to work. You told it to loop over sequence, asking when num is equal to sequence, but one part of the list is not equal to the whole list. To fix this, we use an index. So we say, if item is equal to sequence[i], where is is an index, then we do found +=1. You also had the return statement in the for-loop, while you should get it outside of the for-loop, because it because breaks the loop. I hope this helps.

    def count(sequence, item):
        found = 0
        if sequence == item:
            found += 1
            return found
        else:
            for num in range(len(sequence)):
                if item == sequence[num]:
                    found += 1
            if found > 0:
                return found
            else:
                return False
Rein K.
  • 141
  • 8
0

You can use a recursive function to repeat calls on the count function when the first argument is a list, or use a simple == when it is not. This can equally handle nested lists by walking through the nesting recursively:

def count(sequence, item):
    found = 0
    if isinstance(sequence, list):
        for x in sequence:
            found += count(x, item)
    else:
        return int(item == sequence)
    return found


print count([4,'foo',5,'hi', [5]], 5)
# 2
print count(5, 5)
# 1
Moses Koledoye
  • 77,341
  • 8
  • 133
  • 139
0

I'd use collections.Sequence (or collections.abc.Sequence in Python 3) to determine if the items are sequences (lists, tuples, etc). If you just want to know if the item is in the list, which is what your code seems to be doing in spite of the name count:

from collections import Sequence
# In Python 3 it would be
# from collections.abc import Sequence

def count(sequence, item):
    for i in sequence:
        if item == i or (isinstance(i, Sequence) and item in i):
            return True
    return False

If you want to actually count the number of appearances of item in sequence:

from collections import Sequence
# In Python 3 it would be
# from collections.abc import Sequence

def count(sequence, item):
    found = 0
    for i in sequence:
        if item == i or (isinstance(i, Sequence) and item in i):
            found += 1
    return found

There could be the possibility that a list within sequence contains in turn deeper sublists, and so on, in which case you may want a recursive algorithm. For finding if the element is contained you could go with:

from collections import Sequence
# In Python 3 it would be
# from collections.abc import Sequence

def count(sequence, item):
    for i in sequence:
        if item == i or (isinstance(i, Sequence) and count(i, item)):
            return True
    return False

For actually counting:

from collections import Sequence
# In Python 3 it would be
# from collections.abc import Sequence

def count(sequence, item):
    found = 0
    for i in sequence:
        if item == i:
            found += 1
        elif isinstance(i, Sequence) and item in i:
            found += count(i, item)
    return found

PD: Note that strings are considered sequences, and therefore "b" in "abc" and "b" in ["a", "b", "c"] are both true. If you don't want "b" being considered an element of "abc" (i.e. you want to consider strings atomically, like numbers), you'd have to tune the code a bit. You could replace isinstance(i, Sequence) with isinstance(i, (list, tuple)), or with isinstance(i, Sequence) and not isinstance(i, basestring) (or, in Python 3, isinstance(i, Sequence) and not isinstance(i, (str, bytes))).

jdehesa
  • 58,456
  • 7
  • 77
  • 121