【问题标题】:Elegant way to find min/max in a table (vector of vectors, 2D array) using STL algorithm(s)使用 STL 算法在表(向量的向量、二维数组)中查找最小值/最大值的优雅方法
【发布时间】:2018-12-12 11:21:33
【问题描述】:

假设我们有一个向量向量并希望找到一个最小值(或最大值)(无需知道它们在表中的位置)。什么是完成此任务的优雅方式?

下面包含的显而易见的解决方案是在循环中对每一行运行 std::min_element。但是是否有可能用一个没有循环的语句来做到这一点?可能是 lambda 函数?

注意,关于 SO 已经有一个类似的问题,但实际上并不是我在这里问的问题。

更新:理想的解决方案是仅使用 STL,但如果做不到这一点,看看其他选项会很有趣。

#include <algorithm>
#include <iostream>
#include <vector>

int main()
{
    std::vector<std::vector<double> > test_array=
         {
          {1., 2., 3., 4.},
          {7., 4., 6., 8.},
          {5., -1., 3., 1}
         };
    double min_val(test_array[0][0]);
    double max_val(test_array[0][0]);
    for(auto& row : test_array)
    {
        min_val = std::min(min_val, *std::min_element(row.begin(), row.end()));
        max_val = std::max(max_val, *std::max_element(row.begin(), row.end()));
    }

    cout << "Minimum = " << min_val << std::endl;
    cout << "Maximum = " << max_val << std::endl;
    return 0;
}

【问题讨论】:

  • 问题是算法返回一个迭代器,所以你不能做std::max_element(begin(array), end(array), 0, [](){}),因为你需要在一个向量上返回一个迭代器,而不是在一个元素上:/
  • 使用range-v3,有ranges::view::join 可以将范围范围视为展平范围,那么简单的std::minmax_element 就足够了。
  • @Jarod42 有机会根据它得到答案吗?
  • @MatthieuBrucher:不确定 OP 是否可以使用外部库。
  • 我会投票给@Jarod42。找到一种通过一个迭代器查看向量向量的方法。这可以通过一些知道所有向量的迭代器来完成。或者你将向量的向量删除为一个简单的向量。

标签: c++ algorithm stl


【解决方案1】:

使用range-v3,您可能会使用ranges::view::join 获得平面视图:

std::vector<std::vector<double> > test_array =
{
    {1., 2., 3., 4.},
    {7., 4., 6., 8.},
    {5., -1., 3., 1}
};
auto flatten_view = test_array | ranges::view::join;
const auto p = std::minmax_element(begin(flatten_view), end(flatten_view));
std::cout << "Minimum = " << *p.first << std::endl;
std::cout << "Maximum = " << *p.second << std::endl;

Demo

【讨论】:

  • 谢谢。我赞成您的解决方案,因为它绝对优雅且易于理解,尽管它目前不在 STL 范围内。好吧,我想一个人不能两者兼得。
【解决方案2】:

有多个选项,例如,以下使用 std::accumulate 分别返回包含最小和最大元素的一对数字:

auto res = std::accumulate(a.begin(), a.end(), std::make_pair(a[0][0], a[0][0]),
    [](const auto& current, const auto& v) {
        auto minmax = std::minmax_element(v.begin(), v.end());
        return std::make_pair(std::min(current.first, *minmax.first),
                              std::max(current.second, *minmax.second));
    });

现场演示:https://wandbox.org/permlink/IwMWioewJBg7C67l

【讨论】:

  • 有趣的解决方案。我接受它作为答案,因为它在形式上是正确的。基本上它回答了我的问题——这是可能的,但结果既不优雅也不易于理解。谢谢。
  • @one_two_three 同意,我们不能两者兼得。希望范围能进入 C++20。
猜你喜欢
  • 1970-01-01
  • 2015-10-11
  • 1970-01-01
  • 2017-12-21
  • 2012-01-28
  • 1970-01-01
  • 2015-04-06
  • 2019-11-18
  • 2019-03-31
相关资源
最近更新 更多