【问题标题】:Sort one vector using another in nonincreasing order以非递增顺序使用另一个向量对一个向量进行排序
【发布时间】:2016-08-29 03:50:27
【问题描述】:

这意味着当我按非递增顺序对 v2 进行排序时,v1 应该如下所示:

向量如下所示。

v1  = {0, 5, 5, 2,  10};
v2  = {0 ,2, 6, 20, 5};

输出:

v1 = {2,  5, 10, 5, 0};
v2 = {20, 6,  5, 2, 0};

我试图解决混合 std::sort 和 lambdas 的问题。 这就是为什么我已经阅读了几个关于std::sort 的问题,没有答案可以解决与我类似的问题,所以这就是我问的原因。

我对包含 C++11 和 C++14 的用法或其他特性的答案特别感兴趣。

不是这样的问题:

“我完全不知道该怎么办。”

我知道如何使用 C++98 实现输出,但我想知道是否有更高效、更漂亮的方法来实现。

非常感谢您的帮助:)

【问题讨论】:

  • 你的 C++98 代码是什么样的?
  • 你的输出 v2 少了一个元素
  • 另外,输出是非递增顺序的,恕我直言。
  • 从一对向量转换为一对向量,排序,转换回来。
  • 谷歌搜索“C++ argsort”,得到这个答案:stackoverflow.com/questions/1577475/…

标签: c++ c++11 stl c++14


【解决方案1】:

您可以zipsortunzip

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

//converts two vectors into vector of pairs
template <typename T, typename U>
auto zip(T t, U u) {
  std::vector<std::pair<typename T::value_type,typename U::value_type>> pairs;
  for (size_t i = 0; i < t.size(); ++i){
    pairs.emplace_back(u[i],t[i]);
  }
  return pairs;
}

//converts a vector of pairs, back into two two vectors
template <typename T, typename U, typename V>
void unzip(V pairs, T & t, U & u) {
  for (auto const& it: pairs){
    u.emplace_back(it.first);
    t.emplace_back(it.second);
  }
}


int main(){

  //vectors
  std::vector<int> v1  = {0, 5, 5, 2,  10};
  std::vector<int> v2  = {0 ,2, 6, 20, 5};

  //zip vectors
  auto pairs = zip(v1,v2);

  //sort them
  std::sort(pairs.begin(),pairs.end(),std::greater<>());

  //unzip them
  v1.clear();
  v2.clear();
  unzip(pairs,v1,v2);

  //print
  std::cout << '\n';
  for (auto i: v1) std::cout << i << ' ';
  std::cout << '\n';
  for (auto i: v2) std::cout << i << ' ';
  std::cout << '\n';

} 

【讨论】:

  • std::greater&lt;&gt;() 在没有显式模板参数的情况下如何工作? greater 模板是否具有允许其更通用的默认参数?
  • @AaronMcDaid void 来自 C++14 的专业化。默认类型是 void,它会推导出参数和返回类型。
  • 可以通过定义并行遍历两个向量的 ZipIterator 以及正确定义的迭代器运算符来虚拟地完成压缩和解压缩两个向量,而不是物理上。
【解决方案2】:

好吧,我不知道这是否有效,但这演示了如何使用 std::generatestd::sortstd::transform 执行此操作,以及来自可变 lambda 和迭代器的一些额外调味料.

#include <algorithm>
#include <iostream>

int main()
{
    std::vector<int> v1={0, 5, 5, 2,  10},
        v2  = {0, 2, 6, 20, 5};

    std::vector<int> index;

    index.resize(5);

    std::generate(index.begin(), index.end(),
              [n=0]
              ()
              mutable
              {
                  return n++;
              });

    std::sort(index.begin(), index.end(),
          [&]
          (auto &a, auto &b)
          {
              return v2[b] < v2[a];
          });

    std::vector<int> v1_out, v2_out;

    std::transform(index.begin(), index.end(),
               std::back_insert_iterator<std::vector<int>>(v1_out),
               [&]
               (auto a)
               {
                   return v1[a];
               });

    std::transform(index.begin(), index.end(),
               std::back_insert_iterator<std::vector<int>>(v2_out),
               [&]
               (auto a)
               {
                   return v2[a];
               });

    for (auto n: v1_out)
        std::cout << n << ' ';
    std::cout << std::endl;

    for (auto n: v2_out)
        std::cout << n << ' ';

    std::cout << std::endl;
}

【讨论】:

  • 而不是从 生成 + 可变 lambda, std::iota
  • 感谢您的付出 ;)
  • 有趣的设计,虽然我发现 std::back_inserter 比原始的 std::back_insert_iterator&lt;SomeLongType&gt; 更具可读性。
【解决方案3】:

非常感谢您的所有回答。我找到了一个简单的方法来达到同样的效果,这个想法来自this answer

1。 首先,我使用了我链接的答案中的所有代码,所以它是:

template <typename T>
vector<size_t> sort_indexes(const vector<T> &v)
{

  // initialize original index locations
  vector<size_t> idx(v.size());
  for (size_t i = 0; i != idx.size(); ++i) idx[i] = i;

  // sort indexes based on comparing values in v
  sort(idx.begin(), idx.end(),
       [&v](size_t i1, size_t i2)
       {
         return v[i1] >= v[i2];
       });

  return idx;
}

2.然后我做了一个函数,它将使用第三个向量对第一个向量和第二个向量进行排序。为了实现它,我必须创建一个临时向量,一个用于第一个向量,一个用于第二个,两个 最后一个。

为什么是两个 因为我必须记住第三个向量的排序索引,并且我需要一个临时索引,我将根据排序索引将原始第三个向量的元素推送到该索引。

 void SortByIndexes(vector<int>& Pi,vector<int> &Wi,vector<int>& PidivWi)
    {

      vector<int> Pitemp, Witemp, PidivWitemp,SortedIndexes;

      for (auto i : sort_indexes(PidivWi))
      {

        SortedIndexes.push_back(i);

      }

     for (auto i : SortedIndexes)
      {
        Pitemp.push_back(Pi[i]);
        Witemp.push_back(Wi[i]);
        PidivWitemp.push_back(PidivWi[i]);
      }

      swap(Pi, Pitemp);
      swap(Wi, Witemp);
      swap(PidivWi,PidivWitemp);

    }

3。排序后,只需将排序后的向量与原始向量交换即可。 完成。

谢谢大家。

【讨论】:

  • 是的,这正是要走的路(如果它缺少的话,我会回答)。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2016-09-19
  • 2023-04-04
  • 1970-01-01
  • 2012-07-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多