对 unordered_multimap 键进行平均的更好方法是啥?
Posted
技术标签:
【中文标题】对 unordered_multimap 键进行平均的更好方法是啥?【英文标题】:Is the a better way to do an average of a unordered_multimap key?对 unordered_multimap 键进行平均的更好方法是什么? 【发布时间】:2019-12-03 16:58:17 【问题描述】:我正在我的 unordered_multimap 中搜索获取一个键的所有值,这实际上是堆叠一个 int 和一个表示执行时间(以纳秒为单位)的值。我需要用 一个平均键来替换多键的所有值。
我尝试了一些代码,这个实际上是最有价值的:
std::unordered_multimap<int, std::chrono::nanoseconds> data;
std::chrono::nanoseconds average;
// *filling my map with value*
for (auto & pair : data)
auto range = data.equal_range(pair.first);
for_each (
range.first,
range.second,
[](std::unordered_multimap<int, std::chrono::nanoseconds>::value_type& x)
average = average + x.second;
);
average = average / data.count(pair.first);
data.erase(pair.first);
data.insert(pair.first, average);
我得到的错误error: 'average' is not captured : average = average + x.second;
【问题讨论】:
我不明白这个问题。为什么不在更高的范围内声明average
?
The problem is that average isn't defined out of the for_each loop
- 所以在 for_each 循环中定义平均值。问题解决了!
data.erase
在data
的循环内:哎哟。
正如错误所说,您没有捕获average
。将其添加到 lambda 的捕获列表中。
我做了更改并在更大范围内进行了声明,但仍然无法正常工作
【参考方案1】:
而不是std::for_each
,使用std::accumulate
。
请注意,在 ranged-for 中从 std::unordered_multimap
中删除条目是未定义的行为。填充不同的容器更安全。
std::unordered_multimap<int, std::chrono::nanoseconds> data;
// *filling my map with value*
std::unordered_multimap<int, std::chrono::nanoseconds> new_data;
for (auto it = data.begin(); it != data.end(); ++it)
auto range = data.equal_range(it->first);
auto average = std::accumulate (
range.first,
range.second,
std::chrono::nanoseconds0,
[](auto sum, auto & x)
return sum + x.second;
) / std::distance(range.first, range.second);
new_data.emplace(key, average);
data.swap(new_data);
或者,如果你有 C++17,std::transform_reduce
。
std::transform_reduce(
range.first,
range.second,
std::chrono::nanoseconds0,
std::plus<>,
[](auto & x) return x.second;
)
【讨论】:
我试过这个,但是有很多错误,根本无法编译emplace
真的总是安全的吗?我想它不会导致重新散列,因为大小不会增加,但是新元素的迭代器是否保证在从erase
返回的it
之前排序?
效果很好,在你编辑后我确实改变了,一切都好!谢谢
@walnut 也许?之后填写decltype(data) new_data;
和data.swap(new_data);
可能更安全
@Caleth 是的,那是我的建议。还允许删除 erase
并使用普通的迭代器循环。仅根据 cppreference,因为 C++14 保证 erase
保留迭代器的顺序,并且在这方面它没有说明 emplace
。以上是关于对 unordered_multimap 键进行平均的更好方法是啥?的主要内容,如果未能解决你的问题,请参考以下文章
保证 std::unordered_multimap 中的键唯一性
在 boost::unordered_multimap 中循环遍历 equal_range
如何拥有 unordered_multimaps 的 unordered_multimap