我试图在python中使用dict理解和三元操作来完成以下表达式:
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循环那样起作用吗?谢谢。
发布于 2018-09-19 23:52:37
不要。这似乎是一个好主意,但它实际上是一个可怕的陷阱。使用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)),或者对于对标准库更熟悉一点,
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))
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.00422721728682518Counter在半毫秒内完成,而count代码段都占用了一秒时间。(由于某种第一次运行效果,set版本的运行时似乎更低;交换set和非set版本的顺序通常会逆转这些版本的相对时间。set的重复对这个测试没有帮助,因为输入没有重复。)
对于更长的输入,依赖count将更加昂贵。依赖count很容易就会花费数天的时间来完成Counter仍将在一秒钟内完成的输入。
发布于 2018-09-19 23:38:48
在这里,它实际上比我想象的要简单得多。基本上,您想要的是列表中发生的事情发生的次数,这可以通过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}发布于 2018-09-19 23:38:57
似乎你在试图在一个列表中得到所有值的表象。(如果不是,请告诉我。)以下是我处理这个问题的方法:
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的键值对。
https://stackoverflow.com/questions/52415446
复制相似问题