# 11. Count

#1

Actually, it says that I passed the test, but I wanted to run it in any possibility.
It says that item can be another list, so I was eager to check it out.

I want to add two lists, other shorter then the previous one and check how many times does the longer list contain the smaller one.

This one doesnâ€™t work. I have no idea why.
I know itâ€™s a bit messed up, but after hour of figuring I changed a lot of code, soâ€¦

``````def count(sequence, item):

occurence_count = 0
if type(item) is int or type(item) is float or \
type(item) is str:
for i in sequence:
if i == item:
occurence_count += 1
return occurence_count

elif type(item) is list:
for a, b in zip(sequence, item):
abcount = 0     *The count of matches*
while abcount < len(item):
if a == b:
abcount += 1
break
else:
if abcount == len(item):
occurence_count += 1

return occurence_count
count([1,2,3,4,5,6,7], [1,2,3])
``````

#2

The item you input may be an integer, string, float, or even another list, which means:

``````count([[1,2,3],[4,5,6,7]], [1,2,3])
``````

now `[1,2,3]` must equal `[1,2,3]` which is easy to test, what you do goes much further.

for starters donâ€™t use zip, look:

``````for a, b in zip([1,2,3,4,5,6,7], [1,2,3]):
print a, b
``````

zip() ends one of the lists is completed, so if you want to do:

``````count([1,2,3,4,5,6,7], [4,5,6])
``````

a match will never be found.

#3

What is the other thing to compare two lists, except nested for loop?

#4

nested loops is a good idea, why not use it?

of course there are always multiply ways to solve a problem, we could use list slicing:

``````for i in range(sequence):
``````

then check if the current item in sequence (`sequence[i]`) equals the first item of `item`, then use list slicing to see of the rest of sequence equals `item`

#5

It seems to me that nested for loops take more time to process?
Maybeâ€¦?

And please, explain what slicing is, if you can?

#6

Well, you could try to see which preforms better.

list slicing has been covered in the lessons:

``````print ['a','b','c','d'][:2] # ['a','b']
``````

with the right design, it can be used here

#7

Oh, I remember. I didnâ€™t know it was called that way.
thank you very much

#8

anyway, see how far you get, if you need more help post an updated version of your code

I let you do most of the work, of course i could work out a solution, but that wouldnâ€™t teach you as much. Writing your own solutions teaches you way more

#9

Alright, donâ€™t close the thread until I post the right one, okay?

#10

I only close solved topics, which is currently not the case. I still offer further assistance if needed

The topic is auto-closed 7 days after the last reply

#11

Alright, so now, it apparently works in these cases:
count([1,2,3,4,5], [1,2,3]) - printed 1
count([1,2,3,4,5], [1,2]) - printed 1
, but it doesnâ€™t work in these cases:
count([1,2,3,4,5,6,7], [9])
count([1,2,3,4,5,1,2,3], [1,2,3]) - Instead of printing 2, it prints the else clause after while loop:

Also, I have a question regarding continue and break in nested loops.
How can I return to the 1st for/while loop if I have more then 2 or 3?
In case such as this one:

``````while match_count < len(item):
for i in sequence:
for p in item:
if i == p:
match_count += 1
else:
break
``````

And, how can I return from else clause in while/for loop to while/for loop, in case like this:

``````while match_count < len(item):
....
else:
if match_count == len(item):
occurence_count += 1
match_count -= len(item)
else:
....
``````

This is the code:

``````def count(sequence, item):
occurence_count = 0
if type(item) is int or type(item) is float or \
type(item) is str:
for i in sequence:
if i == item:
occurence_count += 1
return occurence_count
elif type(item) is list:
match_count = 0
while match_count < len(item):
for i in sequence:
for p in item:
if i == p:
match_count += 1
else:
break
else:
if match_count == len(item):
occurence_count += 1
match_count -= len(item)    #This means that if the condition is met
else:                         #match count will return to zero so the while loop can continue
print("Sequence does not contain item")
print(occurence_count)
count([1, 2, 3, 4, 5, 6], [1, 2, 3])
``````

Check this out and let me know what do you think I should change.
Thank you very much, this is very helpful, even though this is easy for you, for me itâ€™s very hard.

#12

never easy. I am going to be honest, i would solve the problem differently, and find it very difficult to see how i could solve the problem your way. I get what you are attempting

I am going to need some time on this.

#13

Alright. I understand.
I just want you to know that even though there are probably functions and methods I can use in order to solve this problem, I want to try to do it my way, because thatâ€™s the real way I will learn to compare difference in complicity once I become better.

If itâ€™s not the problem, can you just answer on two of my questions regarding continuing nested while/for loops/

#14

i think its not very interesting, given its not the way you should go.

i think a better approach to this problem would be looping over `sequence`, but we are going to need indexes so we have to use range:

``````for i in range(len(sequence)):
``````

then if `sequence[i]` equals the first item of `item` (`item[0]`) we should use a `zip()` to loop over the part of `sequence` to compare it with `item` for which we use list slicing:

``````for a, b in zip(sequence[i:i+len(item)], item):
``````

now `if a != b` we can break the loop. Then we add `else` to `for` loop, and increase `match_count` by one. `else` is only reached when loop finished running, and isnâ€™t broken by `break`

an even better solution would to loop over sequence using range, then inside this loop, loop over item using range:

``````for j in range(len(item)):
``````

this way, we could check if `sequence[i] + j` equals `item[j]`, and use the same `for/else` with break strategy, its quit cool given we cleverly use `j` to also get all items of `sequence` list while looping over `item`

#15

Alright, hereâ€™s the code.
Everything seems logical. Your suggestion to remove match_count is good, so I accepted it.
Now I have this code, but it keeps popping the error:
Traceback (most recent call last):
File â€śD:\Python\init1.pyâ€ť, line 30, in
count([1, 2, 3, 4, 5, 6, 1, 2, 3], [1, 2, 3])
File â€śD:\Python\init1.pyâ€ť, line 20, in count
for a, b in list(sequence[i:i+len(item), item]):
TypeError: list indices must be integers or slices, not tuple

Hereâ€™s the code
Presumably, the item will have 3 elements in a list.
I just didnâ€™t know how to add a variable which will add â€śifâ€¦and (aindex + n) == (bindex + n)â€ť

``````def count(sequence, item):
occurrence_count = 0
if type(item) is int or type(item) is bool or type(item) is float or type(item) is str:
for i in sequence:
if i == item:
occurrence_count += 1
else:
continue
elif type(item) is list:
for i in range(0, len(sequence)-len(item)+1):
'''
I put this range limit because it's important not to reach out of list length.
For instance, if I didn't deduct len(item) from len(sequence), the i iterator would go from 0-10.
Which means that equation from following text would, at some point, be: 9:9+(3),
and the limit of sequence is 10.
So instead, I deducted the length of item from sequence and added 1, because i+len(item) doesn't make sense
at the end of the loop because one step was i = 0, so I added that additional step.
'''
for a, b in zip(sequence[i:i+len(item), item]):
aindex = sequence.index(a)
bindex = item.index(b)
if sequence[aindex] == item[bindex] and sequence[aindex+1] == item[bindex+1] \
and sequence[aindex+2] == item[bindex+2]:
occurrence_count += 1
else:
continue
print(occurrence_count)

count([1, 2, 3, 4, 5, 6, 1, 2, 3], [1, 2, 3])

``````

Also, everything but lists works very nicely.

#16

index error might indeed be a problem, we might need to limitate range, which you did, which sounds like a very good idea

Seems your are still struggling for understanding, doesnâ€™t seem like i did a good job of explaining. At any point, feel free to add `print` statement to see what your code is actually doing.

look:

``````# my code
for a, b in zip(sequence[i:i+len(item)], item):
for a, b in zip(sequence[i:i+len(item), item]):
``````

they are not identical. I think its important to understand what lists `zip()` is producing.

actually, i am an idiot. Scratch zip, lets simplify the code for a bit:

``````sequence, item = [1, 2, 3, 4, 5, 6, 1, 2, 3], [1, 2, 3]
total = 0
for i in range(len(sequence)):
if sequence[i] == item[0]:
if sequence[i:i+len(item)] == item:
total += 1
print total
``````

once we determined that the current character in `sequence` equals the first character of `item`, we can simply slice the piece of `sequence` we want to compare with `item`. Much better solution to determine if there is a match

then we could apply some small optimizations:

``````sequence, item = [1, 2, 3, 4, 5, 6, 1, 2, 3], [1, 2, 3]
total = 0
first_item = item[0]
item_length = len(item)
for i in range(len(sequence)):
if sequence[i] == first_item:
if sequence[i:i+item_length] == item:
total += 1
print total
``````

anyway, i know this is a lot to take in.

#17

Yes, I was thinking the same about small optimization.
Let me check if the code works first.
As far as I understood, zip() creates a tuple, but I just added this little thing:

``````for a, b in list(zip(sequence[i:i+len(item)], item[i:len(item)])):
``````

I just need to calculate it first.

I think I can actually manage to do it my way first.

Give me 5 minutes.

#18

When I list a zip file of for instance, in this case:

``````            for a, b in list(zip(sequence[i:i+len(item)], item[0:len(item)])): #not i, but 0
if sequence[a] == item[b] and sequence[a+1] == item[b+1] and sequence[a+2] == sequence[b+2]:
occurrence_count += 1
``````

letâ€™s put some numbers:

``````for i =0
for a, b in list(zip(sequence[0:3], item[0:3])):
if sequence[0] == item[0] and sequence[1] == item[1] and sequence[2] == sequence[2]
occurrence_count += 1

for i = 1
for a, b in list(zip(sequence[1:4], item[0:3])):
if sequence[1] == item[0] and sequence[2] == item[1] and sequence[3] == sequence[2]
occurrence_count += 1

``````

list(zip(shit)) creates this:
[(1,1),(2,2),(3,3], right?

#19

easy enough to find out:

``````print zip([0,1,2,3], [0,1,2,3])
``````

we donâ€™t have to use `for` with `zip()`, and `print` always useful if you want to know something for sure

#20

I did the same thing, but the problem is that
List(zip()) doesnâ€™t create
[1,1,2,2,3,3,4,4,â€¦]
but
[(1,1),(2,2),(3,3)] - tuples, maybe?