用字典计算列表变量

时间:2019-01-14 16:54:29

标签: python python-3.x

我必须编写一个可以计算给定列表中的水果数量的程序。

我尝试了for循环,但没有成功。我也尝试过Counter,但这会删除第二个'banana',但只能识别一个。

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)

我希望这会给我带来很多水果,但我的输出为0

5 个答案:

答案 0 :(得分:2)

您可以从所有水果中构建一个集合并使用它:

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)

返回3-因为True(O(1)集查找的结果)等于1,而False等于0。


在大多数情况下,此解决方案要比Daniel Trugman's solution差,而在其他情况下,则要快一些:

  • 创建集合,它一次访问字典的每个来构建集合-之后,它使用创建的集合来确定某物是否为水果:

考虑:

c = {'banana':'fruit'}
v = ['banana' * 100000]
fixed = set(k for k,v in c.items() if v=="fruit")

dict理解必须直接获得c['banana'] 100000次,并执行100000 c[val] == 'fruit'来检查它是否是水果。这比在构造的集合上检查100000次'banana' in fixed慢。

对于手头的示例,dict comp很好。


大多数情况下,dict-comp更快:

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

输出:

'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 

答案 1 :(得分:2)

只需尝试:

r = sum(1 for val in v if c[val] == 'fruit')

或者,就像建议的@jpp一样(短一点):

r = sum(c[val] == 'fruit' for val in v)

或者,如果您需要速度,例如@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)

说明::访问值并每次进行比较都非常昂贵。在所有键都是水果的情况下,创建一个新字典的成本较低,然后只需忽略这些值即可。这比使用集合更好,因为集合是使用搜索复杂度为O(logN)的平衡树实现的,而字典是使用搜索复杂度为O(1)的哈希图实现的,只要映射中项目的数量不比内部容量大很多...

答案 2 :(得分:0)

首先尝试找出该类型,然后找到重音符号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)

答案 3 :(得分:0)

这是一种解决方案:

res = sum(c[value] == 'fruit' for value in v)

之所以可行,是因为bool被视为int的子类,即布尔值True / False等同于整数1 / {{1} }。

答案 4 :(得分:0)

有些简短(类似于@Daniel Trugman的回答,但稍微简单些):

r = sum(1 for value in c.values() if value == 'fruit')