基于元组值对向量进行排序

Sorting vector based on tuple value

本文关键字:向量 排序 于元组 元组      更新时间:2023-10-16

我有以下数据结构,

typedef vector< tuple<int,int,int> > vector_tuple;

在矢量中,我正在存储tuple<value,count,position>

我想根据计数对向量进行排序,如果计数相同,那么根据位置对向量进行分类。

structure ordering
{
  bool ordering()(....)
  {
    return /// ?
  }
};
int main()
{ 
    std::vector<int> v1{1,1,1,6,6,5,4,4,5,5,5};
    std::vector<int> v2(v1);
    vector_tuple vt;
    std::tuple<int,int,int> t1;
    std::vector<int>::iterator iter;
    int sizev=v1.size();
    for(int i=0; i < sizev ; i++)
    {
         auto countnu = count(begin(v2),end(v2),v1[i]);  
         if(countnu > 0)
         {
           v2.erase(std::remove(begin(v2),end(v2),v1[i]),end(v2));
           auto t = std::make_tuple(v1[i], countnu, i);
           vt.push_back(t);
         }
     }
     sort(begin(vt),end(vt),ordering(get<1>vt); // I need to sort based on count and if count is same, sort based on position.

     for (int i=0; i < vt.size(); i++)
     {
        cout << get<0>(vt[i]) << " " ;
        cout << get<1>(vt[i]) << " " ;
        cout << get<2>(vt[i]) << " n" ;
     }
}

您的比较方法应该看起来像:

auto ordering = [](const std::tuple<int, int, int>& lhs,
                   const std::tuple<int, int, int>& rhs) {
    return std::tie(std::get<1>(lhs), std::get<2>(lhs))
         < std::tie(std::get<1>(rhs), std::get<2>(rhs));
};
std::sort(std::begin(vt), std::end(vt), ordering);

std::tie答案的所有学分都归于Jarod42。

现在,让我们通过创建一个可变模板谓词使其通用:

template<std::size_t...Is>
struct tuple_parts_ascending
{
    template<class...Ts>
    static auto sort_order(const std::tuple<Ts...>& t)
    {
        return std::tie(std::get<Is>(t)...);
    }
    template<class...Ts>
    bool operator()(const std::tuple<Ts...>& l,
                    const std::tuple<Ts...>& r) const
    {
        return sort_order(l) < sort_order(r);
    }
};

我们可以调用它:

sort(begin(vt),end(vt),tuple_parts_ascending<1,2>());

完整代码:

#include <vector>
#include <algorithm>
#include <tuple>
#include <iostream>
using namespace std;
typedef std::vector< std::tuple<int,int,int> > vector_tuple;
template<std::size_t...Is>
struct tuple_parts_ascending
{
    template<class...Ts>
    static auto sort_order(const std::tuple<Ts...>& t)
    {
        return std::tie(std::get<Is>(t)...);
    }
    template<class...Ts>
    bool operator()(const std::tuple<Ts...>& l,
                    const std::tuple<Ts...>& r) const
    {
        return sort_order(l) < sort_order(r);
    }
};
int main()
{
    std::vector<int> v1{1,1,1,6,6,5,4,4,5,5,5};
    std::vector<int> v2(v1);
    vector_tuple vt;
    std::tuple<int,int,int> t1;
    std::vector<int>::iterator iter;
    int sizev=v1.size();
    for(int i=0; i < sizev ; i++)
    {
        auto countnu = count(begin(v2),end(v2),v1[i]);
        if(countnu > 0)
        {
            v2.erase(std::remove(begin(v2),end(v2),v1[i]),end(v2));
            auto t = std::make_tuple(v1[i], countnu, i);
            vt.push_back(t);
        }
    }
    sort(begin(vt),end(vt),tuple_parts_ascending<1,2>());

    for (int i=0; i < vt.size(); i++)
    {
        cout << get<0>(vt[i]) << " " ;
        cout << get<1>(vt[i]) << " " ;
        cout << get<2>(vt[i]) << " n" ;
    }
}

预期结果:

6 2 3
4 2 6
1 3 0
5 4 5

更进一步,我们可以通过允许排序谓词和索引作为参数传递(此解决方案需要c++14),使此操作更加通用和"值得库使用":

namespace detail {
    template<class Pred, std::size_t...Is>
    struct order_by_parts
    {
        constexpr
        order_by_parts(Pred&& pred)
        : _pred(std::move(pred))
        {}
        template<class...Ts>
        constexpr
        static auto sort_order(const std::tuple<Ts...>& t)
        {
            return std::tie(std::get<Is>(t)...);
        }
        template<class...Ts>
        constexpr
        bool operator()(const std::tuple<Ts...>& l,
                        const std::tuple<Ts...>& r) const
        {
            return _pred(sort_order(l), sort_order(r));
        }
    private:
        Pred _pred;
    };
}
template<class Pred, size_t...Is>
constexpr
auto order_by_parts(Pred&& pred, std::index_sequence<Is...>)
{
    using pred_type = std::decay_t<Pred>;
    using functor_type = detail::order_by_parts<pred_type, Is...>;
    return functor_type(std::forward<Pred>(pred));
}

现在我们可以这样排序:

sort(begin(vt),end(vt),
     order_by_parts(std::less<>(),                  // use predicate less<void>
                    std::index_sequence<1, 2>()));  // pack indices into a sequence

使用lambdas:

std::sort(std::begin(vt),std::end(vt),[](const auto& l,const auto& r){
    if(std::get<1>(l)== std::get<1>(r)){
         return std::get<2>(l) < std::get<2>(r);
    }
    return std::get<1>(l) < std::get<1>(r);
});