【问题标题】:Sorting multiple vectors according to one vector [duplicate]根据一个向量对多个向量进行排序[重复]
【发布时间】:2017-05-04 16:35:24
【问题描述】:

我有四个向量,其中包含关于圆心的 x、y、半径和权重信息。我想按重量(从高到低)对它们进行排序,但我真的不知道如何或从哪里开始。如果有帮助的话,我可以将所有向量放在Eigen::Tensor 中,以将收集的数据保存在一个 4d 矩阵中。但除此之外我不知道。

每个向量都包含 134 个元素,但由于只有其中一个需要排序,这意味着排序算法并不重要。

有人提示从哪里开始吗?

【问题讨论】:

标签: c++ sorting vector


【解决方案1】:

您可以创建第 5 个索引向量,根据 4 个向量之一对索引向量进行排序,然后在 O(n) 时间内重新排序所有 4 个向量(并对索引向量进行排序)。根据其中一个(年龄向量)对 3 个向量进行排序的示例。创建索引向量 I 然后根据 A 排序(使用 lambda 比较),然后通过撤消 I 中的“循环”,根据 I 对所有 3 个向量和 I 重新排序。

#include <algorithm>
#include <iostream>
#include <iomanip>
#include <string>
#include <vector>

int main()
{
    std::vector <int> A;                // ages
    std::vector <std::string> N;        // names
    std::vector <int> Z;                // zip codes
    std::vector <size_t> I;             // indices
    int tA;
    std::string tN;
    int tZ;

    A.push_back(37);
    N.push_back("Ted");
    Z.push_back(54211);
    A.push_back(21);
    N.push_back("John");
    Z.push_back(53421);
    A.push_back(31);
    N.push_back("Fred");
    Z.push_back(52422);
    A.push_back(21);
    N.push_back("Sam");
    Z.push_back(51422);
    // display the vectors
    for(size_t i = 0; i < A.size(); i++)
        std::cout << std::setw(6) << N[i]
            << std::setw(8) << Z[i]
            << std::setw(4) << A[i] << std::endl;
    std::cout << std::endl;
    // initialize the vector of indices
    for(size_t i = 0; i < A.size(); i++)
        I.push_back(i);
    // sort I according to A
    std::stable_sort(I.begin(), I.end(),
        [&A](size_t i, size_t j) {return 
        A[i] < A[j];});
    // reorder A, N, Z in place also restore I
    // time complexity is O(n)
    for(size_t i = 0; i < A.size(); i++){
        size_t j, k;
        if(i != I[i]){
            tA = A[i];
            tN = N[i];
            tZ = Z[i];
            k = i;
            while(i != (j = I[k])){
                A[k] = A[j];
                N[k] = N[j];
                Z[k] = Z[j];
                I[k] = k;
                k = j;
            }
            A[k] = tA;
            N[k] = tN;
            Z[k] = tZ;
            I[k] = k;
        }
    }
    // display the sorted vectors
    for(size_t i = 0; i < A.size(); i++)
        std::cout << std::setw(6) << N[i]
            << std::setw(8) << Z[i]
            << std::setw(4) << A[i] << std::endl;
    return 0;
}

【讨论】:

    【解决方案2】:

    使用ranges-v3,您可以执行类似的操作

    ranges::sort(
        ranges::view::zip(xs, ys, radiuses, weights),
        std::greater<>{}, // decreasing order
        [](const auto& t){ return std::get<3>(t); }); // Projection: use weight
    

    Demo

    但是拥有Circle 类是有意义的,这样可以避免压缩数组,并允许进行更短的投影。

    【讨论】:

      【解决方案3】:

      也许首先重组代码并将四个向量转换为一个结构向量更有意义。 类似的东西:

      struct CircleInfo
      {
          int x, y, radius, weight;
      };
      
      std::vector<CircleInfo> circles;
      

      那么,如果你想sort by radius

      #include <vector>
      #include <algorithm>
      #include <iostream>
      
      struct CircleInfo
      {
          int x, y, radius, weight;
      };
      
      int main()
      {
          std::vector<CircleInfo> circles;
          CircleInfo ci1 = { 1,1,1,1 };
          CircleInfo ci2 = { 3,3,3,3 };
          circles.push_back(ci2);
          circles.push_back(ci1);
          std::cout << "before sort circles[0].radius: " << circles[0].radius << std::endl;
          std::sort(circles.begin(), circles.end(), [](const CircleInfo& c1, const CircleInfo& c2) {
              return c1.radius < c2.radius;
          });
          std::cout << "aftern sort circles[0].radius: " << circles[0].radius << std::endl;
      }
      

      输出:

      before sort circles[0].radius: 3
      after sort circles[0].radius: 1
      

      此代码使用std::sort 和自定义函数来比较两个圆。要按半径进行比较,您需要更新它以比较 c1.weightc2.weight

      【讨论】:

      • 我真的很喜欢这个。稍后我也可以从结构中的数据中汲取灵感。谢谢你,帕维尔。
      • 如何为每个点创建一个新的 CircleInfo 结构,而无需手动执行?我想我必须以某种方式使用new,但我不明白它的真正工作方式。
      • @asdfghjkl 您可以在不使用动态分配的情况下创建 CircleInfo:CircleInfo ci12 = { 1,1,1,1 }; 其中值用于x, y, radius, weight。然后使用 push_back: circles.push_back(ci1); 将 CircleInfo 结构添加到向量
      • 我可能只是没有正确理解它,但我有 134 个点需要放入一个结构中。这是我的功能:pastebin.com/LhbSiLTz 我有一个 3d 矩阵 (tensor),其中包含有圆圈的投票。如果投票 >= 阈值,则它们被 1 替换,如果不是,它们被 0 替换,因此局部最大值被标记为 1。然后计算 x,y,半径和重量。但我无法将结构推入向量中。我收到此错误:`Error C2664 'CircleData::CircleData(CircleData &&)': cannot convert argument 1 from 'CircleData *' to 'const CircleData &'
      • 对不起,有时我必须阅读错误,即使我一开始并不理解它们。我应该改写circles.emplace_back(data);。这样就解决了。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2012-07-05
      • 1970-01-01
      • 2010-12-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多