【问题标题】:How can I find the minimum key value from an std::vector of std::map values?如何从 std::map 值的 std::vector 中找到最小键值?
【发布时间】:2016-09-02 20:24:02
【问题描述】:

我有一个 std::vectorstd::map 值:

std::vector<std::map<std::string, double>> dataPoints;

我想找到最低的low 值,74.0。到目前为止,这是我的应用程序:

#include <vector>
#include <map>
#include <iostream>

int main() {
    std::vector<std::map<std::string, double>> dataPoints;

    dataPoints.push_back({{{"high", 77.0}, {"low", 74.0}}});
    dataPoints.push_back({{{"high", 78.0}, {"low", 75.0}}});
    dataPoints.push_back({{{"high", 79.0}, {"low", 76.0}}});
    dataPoints.push_back({{{"high", 80.0}, {"low", 77.0}}});
    dataPoints.push_back({{{"high", 81.0}, {"low", 78.0}}});

    return 0;
}

到目前为止我发现的最接近的是:

double min = std::min_element(dataPoints.begin(), dataPoints.end(), [](std::map<std::string, double> &a, std::map<std::string, double> &b) { return (a["low"] < b["low"]); })["low"];

但这并不完全奏效。

在 JavaScript 中,我可以如下实现:

low = _.min(_.map(dataSegment, function(dataPoints) {
    return dataPoint.low;
}));

【问题讨论】:

  • 您是否总是有两个条目的map?因为如果是这样,您可以通过使用std::vector&lt;std::array&lt;std::pair&lt;std::string, double&gt;,2&gt;&gt; 获得更好的性能
  • 我建议使用 std::pair 而不是 map 来存储 2 个值。像 std::set <:pair double>>.
  • @StoryTeller 不错!谢谢你。性能提升有多明显?另外,向量定义中的“2”参数是什么?
  • 你必须进行基准测试才能看到它到底有多好。但是由于内存的局部性,使用连续的数据结构(向量、数组和对)可以减少缓存未命中。至于 2,它是 std::array 固定大小。
  • 关于您迄今为止得到的答案的评论建议使用std::pair:std::pair 几乎总是适合这项工作的错误工具。您应该改为使用命名字段定义 structstruct Pair { double high; double low; }; std::vector&lt;Pair&gt; dataPoints;。定义数据类型的代码比使用std::make_pair 稍微多一些,但使代码更具可读性。

标签: c++ c++11 dictionary vector stl


【解决方案1】:

你想要min_element,而不是max_element。它会返回一个迭代器,因此您需要取消引用它。

如果"low" 不在地图中,我想您可能不想插入零。所以at 而不是[];这也使我们能够全面地构建整个事物。

double min = std::min_element(dataPoints.cbegin(), dataPoints.cend(),
              [](const std::map<std::string, double> &a,
                 const std::map<std::string, double> &b) {
                     return a.at("low") < b.at("low"); 
              })->at("low");

【讨论】:

  • 哦,是的,抱歉,我是用手机发帖的 :) 感谢您发现这个错字 -- 已修复!
【解决方案2】:

Map 用于存储键/值对。如果您有两个始终相同的键,则使用地图毫无意义。您也不需要对这些键进行排序。

如果给定的第一个值是高的,第二个是低的,那么你可以使用:

std::pair <double, double>

这样,每次添加新值时,都会节省两个 std::string 大小的内存空间。

向量在存储无序序列时很有用。根据您是否希望对数据进行排序,您可以在此处使用一个基于高位或低位进行比较的集合。这将加快找到恒定时间的最小值。

设置:

std::set <std::pair <double, double>>.

Set 是一个有序的容器。如果你的最低点在顶部,你可以使用 begin() 或在底部使用 end()

如果您选择 unsorted,则使用 std::vector。如果您的容器经常更改并且可能,那么您可能需要 std::deque。如果您的容器具有固定大小,并且您不打算修改它,请使用 std::array。在这种情况下,您可以在此处使用 min_element。这种类型的搜索是线性时间。

编辑

如果你想坚持使用 std::vector > 应该可以:

//min_element returns std::vector<std::map<std::string, double>>::iterator
auto minDataPoint = std::min_element(dataPoints.begin(), dataPoints.end(), [](std::map<std::string, double> &a, std::map<std::string, double> &b) { 
    return (a["low"] < b["low"]); 
});

std::cout<<"low "<<(*minDataPoint)["low"];

在这里测试:http://ideone.com/sdG6fk

【讨论】:

  • 我有点困惑,为什么我想要 std::pair 与集合或向量。我希望能够通过键关联地访问数据值;例如数据点[“低”]。不会使用 std::pair 使这不可能吗?
  • 如果你使用一对 dataPoint["high"] 将成为 dataPoint.first 和 dataPoint["low"] 将成为 dataPoint.second。你不需要钥匙,因为你只有“高”和“低”(除非你有更多?)。关联 2 个键只是多余的。唯一要确保您输入的值是按该顺序排列的。
  • 是的,我实际上还有更多……大约 100 个。高、低、开、关、rsi7、rsi5、stochasticK、stochasticD 等。
  • 编辑了我对 std::vector 的答案<:map double>>
猜你喜欢
  • 1970-01-01
  • 2019-02-05
  • 2019-04-19
  • 1970-01-01
  • 2018-04-21
  • 1970-01-01
  • 2010-12-12
  • 2014-09-10
  • 2022-01-02
相关资源
最近更新 更多