[英]Efficient way to transform dict values
例如,假设我正在计算某些类别中某些变量的平均值。 实现此计算的一种方法如下:
from collections import defaultdict
avg = defaultdict(lambda:[0,0])
for cat_name, val in data:
cat = avg[cat_name]
cat[0] += 1
cat[1] += val
avg = { cat: s/n for cat,(n,s) in avg.items() }
这需要从原始字典创建一个新字典。
或者,除法可以像这样在循环中完成:
for cat,(n,s) in avg.items():
avg[cat] = s/n
这不会创建新字典 object,但需要在每次迭代时进行键查找,这具有相同的复杂性。
问题是,不需要更改字典的结构,因此实际上不需要 hash 表查找。 旧值可以直接替换新值。 但这可以在 python 中完成吗?
在 C++20 中,可以按照以下方式做一些事情:
std::unordered_map<std::string,std::variant<std::tuple<unsigned,double>,double>> avg;
// loop over data to accumulate counts and sums
for (auto& [cat,x] : avg) {
auto [n,s] = x.get<0>();
x = s/n;
}
就地转换字典值。
有没有办法在 python 中做类似的事情?
附录:我只用计算平均值的问题作为一个具体的例子。 问题是关于字典值的有效转换。
虽然list
可用于模拟引用类型,但我正在考虑的解决方案是获取对字典 object 的底层存储的可变访问权限。类似于items()
方法,但返回的是可变内容tuple
s。 或者可能是一个 function 接受一个dict
和一个回调 function 用于转换值,a la map
,但就地。 如果散文不清楚,可以使用以下内容:
for x in dict_instance.mutable_items():
x.value = x.value[1]/x.value[0]
或者
dict_instance.transform_values(lambda v: v[1]/v[0])
附录 2 :我也意识到我可以通过这样做来改变原始列表元素之一的含义,比如从总和到平均值:
for val in avg.values():
val[1] = val[1]/val[0]
我想知道是否有办法替换整个值 object 并避免查找。
实际上,您可以使用列表技巧。
from collections import defaultdict
# You use list object for average
avg = defaultdict(lambda:[0,0, list([0])])
for cat_name, val in data:
cat = avg[cat_name]
cat[0] += 1
cat[1] += val
for _, (s, n, lst) in avg.items():
lst[0] = s / n
该解决方案不需要密钥查找,但会增加 memory 的使用。
或者
如果total of val 变量只是使用平均过程,则可以使用增量平均。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.