简体   繁体   English

如何根据另一个向量的排序对向量进行排序?

[英]How can I sort a vector based on sort of another vector?

I have a four vectors that I want to sort in relation to each other.我有四个向量,我想对其进行排序。

vector<string> color;
vector<string> shape;
vector<int> size;

Each vector is the same size each vector element is tied to each other such that it forms a row每个向量的大小相同,每个向量元素相互关联,形成一行

{color[0], shape[0], size[0]}
{color[1], shape[1], size[1]}
{color[2], shape[2], size[2]}, etc

So what I am trying to do is sort the color vector by color and sort the other two vectors based on the rearranged color vector.所以我想要做的是按颜色对颜色向量进行排序,并根据重新排列的颜色向量对其他两个向量进行排序。 Then within every group of colors (ie red) I want to sort by shape and rearrange the size vector based on that sort.然后在每组颜色(即红色)中,我想按形状排序并根据该排序重新排列大小向量。 And then finally I want to sort the size vector within each group of color and shape.最后我想对每组颜色和形状中的大小向量进行排序。 I think I know how to do it but it feels very very messy and difficult to conceptualize/read (I'm still new to C++).我想我知道该怎么做,但是感觉非常非常混乱并且难以概念化/阅读(我还是 C++ 的新手)。 Is there an easy way to accomplish something like this?有没有一种简单的方法来完成这样的事情?

For example I want to do something like this:例如,我想做这样的事情:

Blue    Circle      1   ->    Red   Triangle    1           
Red     Triangle    1   ->    Red   Triangle    2
Blue    Circle      3   ->    Red   Triangle    3
Red     Triangle    3   ->    Red   Circle      1
Red     Circle      2   ->    Red   Circle      2
Blue    Triangle    1   ->    Red   Circle      3
Red     Circle      1   ->    Blue  Triangle    1
Blue    Triangle    3   ->    Blue  Triangle    2
Red     Circle      3   ->    Blue  Triangle    3
Blue    Circle      2   ->    Blue  Circle      1
Blue    Triangle    2   ->    Blue  Circle      2
Red     Triangle    2   ->    Blue  Circle      3

Like John pointed out, you should make a single struct , and then make a std::vector , which you can then sort on color.就像约翰指出的那样,您应该制作一个struct ,然后制作一个std::vector ,然后您可以对颜色进行排序。 Here is a solution:这是一个解决方案:

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

struct MyStruct
{
    std::string color;
    std::string shape;
    int size;

    MyStruct(std::string co, std::string sh, int si): 
        color{co}, shape{sh}, size{si} {};
};

bool MyComp(MyStruct a,MyStruct b)
{ 
    auto f = [](unsigned char c){ return std::tolower(c);};
    std::transform(a.color.begin(), a.color.end(), a.color.begin(),f);
    std::transform(b.color.begin(), b.color.end(), b.color.begin(),f);

    return (a.color < b.color); 
}

int main() {

    std::vector<MyStruct> MyVec;

    MyVec.emplace_back("Blue","Circle",1); 
    MyVec.emplace_back("Red","Triangle",1);  
    MyVec.emplace_back("Blue","Circle",3);
    MyVec.emplace_back("Red","Triangle",3);   
    MyVec.emplace_back("Red","Circle",2);  
    MyVec.emplace_back("Blue","Triangle",1);   
    MyVec.emplace_back("Red","Circle",1);   
    MyVec.emplace_back("Blue","Triangle",3);   
    MyVec.emplace_back("Red","Circle",3);  
    MyVec.emplace_back("Blue","Circle",2);  
    MyVec.emplace_back("Blue","Triangle",2);   
    MyVec.emplace_back("Red","Triangle",2);

    std::sort(MyVec.begin(), MyVec.end(), MyComp);

    for(auto s : MyVec)
        std::cout << s.color << " " << s.shape  << " " << s.size << std::endl; 

    return 0;
}

You can run the code online to see the following output:您可以在线运行代码以查看以下输出:

Blue Circle 1
Blue Circle 3
Blue Triangle 1
Blue Triangle 3
Blue Circle 2
Blue Triangle 2
Red Triangle 1
Red Triangle 3
Red Circle 2
Red Circle 1
Red Circle 3
Red Triangle 2

You should make a single Shape class or struct, and then make a std::vector<Shape> , which you can then sort on color, primarily, followed by your other parameters.您应该创建一个Shape类或结构,然后创建一个std::vector<Shape> ,然后您可以对颜色进行排序,主要是对其他参数进行排序。 You define an overloaded operator< so that the std::sort function will find it.您定义了一个重载operator<以便std::sort函数可以找到它。

It would look like this:它看起来像这样:

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

struct Shape
{
    std::string color_;
    std::string shape_;
    int size_;

    Shape(const std::string& color, const std::string& shape, int size)
        : color_(color)
        , shape_(shape)
        , size_(size)
    {}

    // returns true if this shape is less than the other shape
    // "less than" is up to us: here we give priority to color, then shape, then size
    bool operator<(const Shape& other) const
    {
        // std::tie makes lexicographical compare of complex structures easy!
        return (std::tie(color_, shape_, size_) <
                std::tie(other.color_, other.shape_, other.size_));
    }

    friend std::ostream& operator<<(std::ostream& os, const std::vector<Shape>& shapes)
    {
        for (auto& shape : shapes)
        {
            os << shape.color_ << " " << shape.shape_ << " " << shape.size_ << "\n";
        }

        return os;
    }
};

int main(int argc, char** argv)
{
    std::vector<Shape> shapes;

    shapes.emplace_back("Blue", "Circle", 1);
    shapes.emplace_back("Red", "Triangle", 1);
    shapes.emplace_back("Blue", "Circle", 3);
    shapes.emplace_back("Red", "Triangle", 3);
    shapes.emplace_back("Red", "Circle", 2);
    shapes.emplace_back("Blue", "Triangle", 1);
    shapes.emplace_back("Red", "Circle", 1);
    shapes.emplace_back("Blue", "Triangle", 3);
    shapes.emplace_back("Red", "Circle", 3);
    shapes.emplace_back("Blue", "Circle", 2);
    shapes.emplace_back("Blue", "Triangle", 2);
    shapes.emplace_back("Red", "Triangle", 2);

    std::cout << "Pre sorted vector:\n";
    std::cout << shapes;

    // std::sort by default will use the operator< for the types
    // being sorted, if it's available
    std::sort(shapes.begin(), shapes.end());

    std::cout << "\nPost sorted vector:\n";
    std::cout << shapes;
}

This gives the output:这给出了输出:

Pre sorted vector:
Blue Circle 1
Red Triangle 1
Blue Circle 3
Red Triangle 3
Red Circle 2
Blue Triangle 1
Red Circle 1
Blue Triangle 3
Red Circle 3
Blue Circle 2
Blue Triangle 2
Red Triangle 2

Post sorted vector:
Blue Circle 1
Blue Circle 2
Blue Circle 3
Blue Triangle 1
Blue Triangle 2
Blue Triangle 3
Red Circle 1
Red Circle 2
Red Circle 3
Red Triangle 1
Red Triangle 2
Red Triangle 3

First solution第一个解决方案

One way to solve the problem is to not sort the vectors, but instead to produce a new vector of indexes, let's name it I , such that the items at position j in the sorted vectors are at position I[j] in the current unsorted vectors.解决问题的一种方法是不对向量进行排序,而是生成一个新的索引向量,让我们将其命名为I ,这样已排序向量中位置j处的项目位于当前未排序中的位置I[j]向量。

It is easy to produce this indexing vector by initializing it with the increasing values 0 .. n-1 and sorting the vector with a custom comparison function:通过使用递增值0 .. n-1对其进行初始化并使用自定义比较函数对向量进行排序,可以轻松生成此索引向量:

std::vector<int> I(N);
std::iota(begin(I), end(I), 0);
std::sort(begin(I), end(I), [&](int ia, int ib) { return color[ia] < color[ib]; });
// this is a simplified comparison function to not clutter the code

Now if you want to access the shape of the 3rd element in the sequence sorted by color you write:现在,如果要访问按color排序的序列中第三个元素的shape ,请编写:

auto shape3 = shape[I[3]];

Second solution第二种解决方案

The first solution works, but it may not be to your liking for many reasons.第一个解决方案有效,但由于多种原因,它可能不符合您的喜好。 Maybe you don't like the fact that it randomizes memory accesses (and the associated penalty) when you walk the items in ascending order.也许您不喜欢这样一个事实,即当您按升序遍历项目时,它会随机化内存访问(以及相关的惩罚)。 Or maybe you really need to sort the vectors because you have to pass them to another component.或者您可能真的需要对向量进行排序,因为您必须将它们传递给另一个组件。

In that case, you can still use the first method as a first step, and then reorder the vectors based on the indexes just computed.在这种情况下,您仍然可以使用第一种方法作为第一步,然后根据刚刚计算的索引对向量重新排序。 Here is an example of such reordering for the shape vector:以下是对shape向量进行此类重新排序的示例:

std::vector<std::string> tmp_shape;
tmp_shape.reserve(N);
for(int j=0; j<N; ++j)
    tmp_shape.emplace_back(std::move(shape[I[j]]));
shape.swap(tmp_shape);

Obviously you need to do that for the three vectors to maintain their relationship.显然,您需要为三个向量执行此操作以保持它们的关系。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM