【问题标题】:Comparing and sorting elements in tuple比较和排序元组中的元素
【发布时间】:2018-03-01 07:43:11
【问题描述】:

我有一个vector <tuple<int a, int b, Vec4i c>>,并且我已经按照 a 对元组进行了升序排序。结构是这样的。

vect = { 42,324,{}; //[0]
         43,231,{};
         45,97 ,{};
         73,32 ,{}; //[1]
         112,87,{};
         114,249,{}; //[2]
        }

如果元素之间的差异小于 5,我正在尝试比较“a”并将它们分组。if(a[i+1]-a[i] >= 5

在每个组中,找到 b 的最大元素并将关联的 c 推回到新向量。

元组的实现如下:

    vector<Vec4i> horiz;
    vector<int> ly, lx;                                                 
    using tuple_t = std::tuple<int, int, Vec4i>;
    vector <tuple_t> vect;
    int n = ly.size();
    auto sort_A = [&](tuple_t lhs, tuple_t rhs)
    { return (get<0>(lhs) < get<0>(rhs)); };
    for (int i = 0; i < n; i++) 
        vect.push_back(make_tuple(ly[i],lx[i],horiz[i]));
    sort(vect.begin(), vect.end(), sort_A);

【问题讨论】:

  • 是的,没错。你必须实现自己的Compare
  • 实现你的比较功能,它会更容易给你建议。 “是否正确”是什么意思?
  • 如果你有a40, 44, 48, 52, 56 等,那是一组吗?
  • 该死的,这是一个好问题,我没有考虑过。我理想的分组是 {40,44},{48,52},{56}

标签: c++ vector tuples


【解决方案1】:

你不需要复制到子向量中,你只需要用迭代器记录范围是什么。

#include <vector>
#include <tuple>
#include <algorithm>
#include <numeric>

struct Vec4i {};

int main()
{
    using tuple_t = std::tuple<int, int, Vec4i>;
    std::vector<tuple_t> tuples;
    tuples.push_back(std::make_tuple( 42, 32,Vec4i{}));
    tuples.push_back(std::make_tuple( 43,231,Vec4i{}));
    tuples.push_back(std::make_tuple( 45, 97,Vec4i{}));
    tuples.push_back(std::make_tuple( 73,324,Vec4i{}));
    tuples.push_back(std::make_tuple(112, 87,Vec4i{}));
    tuples.push_back(std::make_tuple(114,249,Vec4i{}));

  // Finds the end of a group
    auto next_group = [](const tuple_t & lhs, const tuple_t & rhs) 
    { return (std::get<0>(rhs) - std::get<0>(lhs)) > 5; };

    using iter_t = std::vector<tuple_t>::iterator;
  // Collect up the groups as iterators
    std::vector<std::pair<iter_t, iter_t>> iters;
    for (iter_t it = tuples.begin(), next; it != tuples.end(); it = next)
    {
      // Original grouping, long runs are one group
        next = std::adjacent_find(it, tuples.end(), next_group);
      // only advance next if it is not end
        next += (next != tuples.end());
        iters.emplace_back(it, next);

      // Variant grouping, compares to first element of group
        next = it;
        while(next != tuples.end() && !next_group(*it, *next)) 
        { ++next; }
        iters.emplace_back(it, next);
    }

    auto compare_b = [](const tuple_t & lhs, const tuple_t & rhs) 
    { return std::get<1>(lhs) < std::get<1>(rhs); };

  // Operate on a pair of iter_t as a range, finding the maximum b 
    auto get_max_c = [&](std::pair<iter_t, iter_t> pair) 
    { return std::get<2>(*std::max_element(pair.first, pair.second, compare_b)); };

    std::vector<Vec4i> results;
    std::transform(iters.begin(), iters.end(), std::back_inserter(results), get_max_c);
}

【讨论】:

  • 通过定义 struct { int a; int b; Vec4i c; } 而不是使用 std::tuple 会更容易,因为您可以使用标识符 a bc
  • 非常感谢您的评论,但是当我实现代码iter_t next = std::adjacent_difference(it, tuples.end(), next_group); 时,它显示了没有合适的用户定义转换的错误。知道如何解决吗?
  • 糟糕,原来是adjacent_findadjacent_difference 在别处
  • 我为“附近”as 添加了第二个分组规则。你应该决定你更喜欢哪一个
  • 我收到C2664 cannot convert argument 1 from 'std::tuple&lt;int,int,cv::Vec4i&gt;' to 'iter_t'C2679 binary '=': no operator found which takes a right-hand operand of type 'std::_Vector_iterator&lt;std::_Vector_val&lt;std::_Simple_types&lt;_Ty&gt;&gt;&gt;' 的错误
【解决方案2】:

在元组中复制列表初始化将不起作用,您必须求助于使用 make_tuple。您可以使用 std::tie 与元组关联。我不能完全理解你的问题,但我给你一个伪代码来查找'vect'中的最高元素(根据参数'b'),如下所示:

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

using namespace std;

struct Vec4i
{
    int i1;
    int i2;
    int i3;
    int i4;
    Vec4i() { i1=i2=i3=i4 = 0;}
    Vec4i(int i11,int i21,int i31,int i41) { i1=i11; i2=i21; i3=i31; i4 = i41;}    
};

int main()
{
    typedef tuple<int, int, Vec4i> foo_t;
    vector <foo_t> vect;
    vect.push_back( make_tuple( 42, 32,Vec4i(1,2,3,4)));
    vect.push_back( make_tuple( 43,231,Vec4i(2,3,4,5)));
    vect.push_back( make_tuple( 45, 97,Vec4i(3,4,5,6)));
    vect.push_back( make_tuple( 73,324,Vec4i(4,5,6,7)));
    vect.push_back( make_tuple(112, 87,Vec4i(5,6,7,8)));
    vect.push_back( make_tuple(114,249,Vec4i(6,7,8,9)));


    auto result = std::max_element(vect.begin(),vect.end(),
                                    [](const foo_t& lhs,const foo_t& rhs)
                                    {
                                                int a1,b1,a2,b2;
                                                Vec4i v1,v2;
                                                tie(a1,b1,v1) = lhs;
                                                tie(a2,b2,v2) = rhs;
                                                return b1<b2;
                                    } );

        int a,b;
        Vec4i v;
        tie(a,b,v) = *result;
        cout <<"a ="<<  a << " "<<"b ="<<  b << " "<<"i1 ="<<  v.i1 << " "<<"i2 ="<<  v.i2 << " "<<"i3 ="<<  v.i3 << " "<<"i4 ="<<  v.i4 <<endl;


}

结果是:

a =73 b =324 i1 =4 i2 =5 i3 =6 i4 =7

【讨论】:

  • 这不会按附近的a 值进行分组
  • @Caleth:我无法理解他想如何按参数 a 进行分组
猜你喜欢
  • 1970-01-01
  • 2018-06-14
  • 1970-01-01
  • 2022-12-17
  • 2016-03-25
  • 1970-01-01
  • 1970-01-01
  • 2018-04-19
  • 1970-01-01
相关资源
最近更新 更多