Jos*_*ood 0 python ternary python-3.x dictionary-comprehension
我正在尝试使用 dict 理解和 python 中的三元运算来执行以下表达式:
for num in ar:
if num in seen_dict:
seen_dict[num] += 1
else:
seen_dict[num] = 1
Run Code Online (Sandbox Code Playgroud)
我试过这个:
seen_dict = { num: seen_dict[num] += 1 for num in ar if num in seen_dict else seen_dict[num] = 1}
Run Code Online (Sandbox Code Playgroud)
及其几个排列,但我不断收到语法错误。可以做我想做的吗?
更新
这是正确的语法,但不是我的 dict 只返回 1:
seen_dict = { num: (seen_dict[num] + 1) if num in seen_dict else 1 for num in ar }
有人可以解释为什么这与 for 循环的功能不同吗?谢谢你。
别。它看起来就像使用字典推导的,这应该是一个不错的主意,但它实际上是一个可怕的陷阱。使用collections.Counter
:
import counts
seen_dict = collections.Counter(ar)
Run Code Online (Sandbox Code Playgroud)
或者如果你不想这样做,那就坚持循环。
尝试使用 dict 推导式的问题在于,dict 推导式没有很好的方法来维护状态或交错每个键的值的计算。每个值都必须在单个表达式中计算。相比之下,解决计数问题的最佳方法是进行单次传递ar
并随时更新每个元素的计数。
理解的限制会导致非常低效的尝试,例如
seen_dict = {val: ar.count(val) for val in ar}
Run Code Online (Sandbox Code Playgroud)
这使得传递次数ar
等于长度ar
,或者稍微更有效但仍然非常不理想的
seen_dict = {val: ar.count(val) for val in set(ar)}
Run Code Online (Sandbox Code Playgroud)
只需要len(set(ar))
通过,或者对标准库比较熟悉的人,
from itertools import groupby
seen_dict = {val: sum(1 for _ in group) for val, group in groupby(sorted(ar))}
Run Code Online (Sandbox Code Playgroud)
这至少不是二次时间,但对于长度为 n 的时间仍然是 O(nlogn) ar
。
如果我们使用 input 对这四个片段进行计时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()))
Run Code Online (Sandbox Code Playgroud)
我们得到以下输出:
0.0005530156195163727
1.0503493696451187
1.0463058911263943
0.00422721728682518
Run Code Online (Sandbox Code Playgroud)
Counter
在半毫秒内完成,而count
片段都需要一秒钟。(set
由于某种首次运行效果减慢了另一个版本的速度,该版本的运行时间似乎较低;交换set
和非set
版本通常逆转这些版本的相对定时的重复数据删除。set
没有帮助这个测试,因为输入没有重复。)
对于更长的输入,依赖count
将更加昂贵。依赖count
可能很容易花费数天时间才能Counter
完成仍然可以在一秒内完成的输入。
归档时间: |
|
查看次数: |
1619 次 |
最近记录: |