我正在尝试使用dict理解和python中的三元运算来执行以下表达式:
for num in ar:
if num in seen_dict:
seen_dict[num] += 1
else:
seen_dict[num] = 1
我尝试过:
seen_dict = { num: seen_dict[num] += 1 for num in ar if num in seen_dict else seen_dict[num] = 1}
及其几个排列,但我不断收到语法错误。可以做我想做的事吗?
更新
这是正确的语法,但我的字典不是仅返回1:
seen_dict = { num: (seen_dict[num] + 1) if num in seen_dict else 1 for num in ar }
有人可以解释为什么这与for循环的功能不同吗?谢谢。
答案 0 :(得分:2)
不要。 似乎就像使用dict理解那样,应该是一个好主意,但这实际上是一个可怕的陷阱。使用collections.Counter
:
import counts
seen_dict = collections.Counter(ar)
或者如果您不想这样做,那么请坚持循环。
尝试使用dict理解的问题是dict理解没有很好的方法来维持状态或交错每个键的值的计算。每个值必须在单个表达式中计算。相反,解决计数问题的最佳方法是对ar
进行一次遍历,并随需更新每个元素的计数。
理解力的限制会导致像这样的极其低效的尝试
seen_dict = {val: ar.count(val) for val in ar}
这使得ar
上的通过次数等于ar
的长度,或者虽然效率更高但仍然非常不理想
seen_dict = {val: ar.count(val) for val in set(ar)}
只需通过len(set(ar))
,或仅对a bit more familiar with the standard library人通过,
from itertools import groupby
seen_dict = {val: sum(1 for _ in group) for val, group in groupby(sorted(ar))}
至少不是二次时间,但对于长度n ar
仍为O(nlogn)。
如果我们使用输入list(range(10000))
run a timing中的这四个摘要:
from collections import Counter
from itertools import groupby
from timeit import timeit
ar = list(range(10000))
print(timeit('Counter(ar)', number=1, globals=globals()))
print(timeit('{val: ar.count(val) for val in ar}', number=1, globals=globals()))
print(timeit('{val: ar.count(val) for val in set(ar)}', number=1, globals=globals()))
print(timeit('{val: sum(1 for _ in group) for val, group in groupby(sorted(ar))}',
number=1, globals=globals()))
我们得到以下输出:
0.0005530156195163727
1.0503493696451187
1.0463058911263943
0.00422721728682518
Counter
会在半毫秒内完成,而count
片段均要花费一秒钟以上。 (set
版本的运行时间似乎较低,这是由于某种首次运行效果会降低其他版本的运行速度;交换set
和非set
版本的顺序通常会相反set
的重复数据删除在此测试中无济于事,因为输入没有重复。)
对于更长的输入,依赖count
的代价甚至更高。依靠count
可以很容易地花费几天时间,而Counter
仍会在一秒钟之内完成。
答案 1 :(得分:1)
在这里,它实际上比我想象的要简单。基本上,您想要的是列表中某事物发生的次数,您可以通过说ar.count(num)
来完成。您可以轻松地做到这一点,而无需像这样的三元运算符:
ar = [1,2,3,2]
seen_dict = { num:ar.count(num) for num in ar}
print(seen_dict)# {1:1, 2:2, 3:1}
答案 2 :(得分:-1)
似乎您正在尝试获取列表中所有值的外观。 (如果不是,请告诉我。)这是我的处理方法:
seen_dict = {num: arr.count(num) for num in list(set(arr))}
说明:
arr.count(num)
:list.count(element)
方法返回element
中list
的出现次数set(arr)
:创建一个set
对象,当该对象转换回列表时,它将删除所有重复项,换句话说,将获得列表的所有不同值list(set(arr))
:arr
字典返回的键值对为number
-# of appearances of number in arr
。