Reputation: 21
I have to make a program that can count the number of fruits in a given list.
I've tried a for
loop but didn't have any success. I have also tried a Counter
but that would remove the second 'banana'
and only recognizes one.
c = { 'banana': 'fruit', 'apple': 'fruit', 'pizza': 'fastfood', 'fries': 'fastfood' }
v = [ 'fries', 'banana', 'banana', 'apple', 'pizza' ]
r = len([v for v in c if c.items() == 'fruit' in c.value()])
print(r)
I expected that this would give me the number of fruits but instead, I have an output of 0
.
Upvotes: 1
Views: 122
Reputation: 51643
You can construct a set from all fruits and use that:
c = { 'banana': 'fruit', 'apple': 'fruit', 'pizza': 'fastfood', 'fries': 'fastfood' }
# collect all fruits into a set that only contains fruit
fixed = set(k for k,v in c.items() if v=="fruit") # cheating by creating the set in setup ;)
v = [ 'fries', 'banana', 'banana', 'apple', 'pizza' ]
r = sum(f in fixed for f in v)
print(r)
Returns 3 - because True
( the result of the O(1) set lookup) equals to 1 and False
equals 0.
This solution is worse then Daniel Trugman's solution under most conditions, in other conditions it is slightly faster:
Consider:
c = {'banana':'fruit'}
v = ['banana' * 100000]
fixed = set(k for k,v in c.items() if v=="fruit")
The dict-comprehension directly has to acces the value of c['banana']
100000 times and do 100000 c[val] == 'fruit'
to check if it is a fruit. This is slower than checking 100000 times 'banana' in fixed
on the constructed set.
For the example at hand the dict comp is fine.
Most of the time the dict-comp is faster:
setup_code = """
c = { 'banana': 'fruit', 'apple': 'fruit', 'pizza': 'fastfood', 'fries': 'fastfood' }
v = [ 'fries', 'banana', 'banana', 'apple', 'pizza' ]
fixed = set(k for k,v in c.items() if v=="fruit")
"""
setup_code2 = """
c = { 'banana': 'fruit', 'apple': 'fruit', 'pizza': 'fastfood', 'fries': 'fastfood' }
v = ['banana']*1000
fixed = set(k for k,v in c.items() if v=="fruit")
"""
using_set = """
# collect all fruits into a set that only contains fruit
r = sum(1 if f in fixed else 0 for f in v)
"""
using_dict_comp = """
r = sum(1 for val in v if c[val] == 'fruit')
"""
import timeit
print("set:", timeit.timeit(using_set,setup=setup_code,number=10000))
print("dict:", timeit.timeit(using_dict_comp,setup=setup_code,number=1000))
print("set:", timeit.timeit(using_set,setup=setup_code2,number=10000))
print("dict:", timeit.timeit(using_dict_comp,setup=setup_code2,number=10000))
Output:
'set:', 0.0069959163665771484
'dict:', 0.0006661415100097656
'set:', 0.6653687953948975 # this "fasteness" goes away as soon as more items are in the set
'dict:', 0.7533159255981445
Upvotes: 2
Reputation: 8501
Just try:
r = sum(1 for val in v if c[val] == 'fruit')
Or, like @jpp suggested (a bit shorter):
r = sum(c[val] == 'fruit' for val in v)
Or, if you need speed, like @Patrick Artner:
ctag = { k: v for k, v in c.items() if v == 'fruit' }
r = sum(1 for val in v if val in ctag)
Explanation: Accessing the value and comparing each time is quite expensive. It is cheaper to create a new dictionary where all keys are fruits, and then simply ignore the values. This is better than using a set, because sets are implemented using balanced trees with search complexity of O(logN) whereas dicts are implemented using hashmaps with search complexity of O(1) as long as the number of the items in the map doesn't exceed the inner capacity by much...
Upvotes: 2
Reputation: 123453
Something short (similar to @Daniel Trugman's answer but slightly simpler):
r = sum(1 for value in c.values() if value == 'fruit')
Upvotes: 0
Reputation: 164653
Here's one solution:
res = sum(c[value] == 'fruit' for value in v)
This works because bool
is treated as a subclass of int
, i.e. Boolean True
/ False
are equivalent to integers 1
/ 0
.
Upvotes: 0
Reputation: 3964
Try this first figure out type then find occurrences of keys of dictonary c
c = { 'banana': 'fruit', 'apple': 'fruit', 'pizza': 'fastfood', 'fries':'fastfood' }
v = [ 'fries', 'banana', 'banana', 'apple', 'pizza' ]
result = [c[i] for i in v] #this will iterate and give the type of element
output={}
for key in c.values():
output[key] =str(result.count(key))
print(output)
Upvotes: 0