Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C++, Sort One Vector Based On Another One

The best example I've got is that I want to sort Names based on their Score.

vector <string> Names {"Karl", "Martin", "Paul", "Jennie"}; vector <int> Score{45, 5, 14, 24}; 

So if I sort the score to {5, 14, 24, 45}, the names should also be sorted based on their score.

like image 357
Krillex Avatar asked May 21 '16 22:05

Krillex


People also ask

How do you sort a vector based on another?

Case 1 : Sorting the vector elements on the basis of first element of pairs in ascending order. This type of sorting can be achieved using simple “ sort() ” function. By default the sort function sorts the vector elements on basis of first element of pairs.

Can we sort vector of vector?

A vector in C++ can be easily sorted in ascending order using the sort() function defined in the algorithm header file. The sort() function sorts a given data structure and does not return anything. The sorting takes place between the two passed iterators or positions.

How do you sort a vector order in reverse?

Use std::sort (or std::stable_sort ) To get a stable sort, go with std::stable_sort , which uses the mergesort algorithm. The two-arg version of the std::sort algorithm sorts the vector in ascending order using operator< . To get the descending order, make a call to std::reverse after std::sort .

How do you add a pair to a vector?

The standard solution to add a new std::pair to a vector of pairs is using the std::emplace_back(T&&... args) function, which in-place construct and insert a pair at the end of a vector, using the specified arguments for its constructor. Note that this function is added in C++11.


2 Answers

An alternative to consolidating the names and scores into a single structure is to create an index list and sort that:

 std::vector<int> indices(Names.size());  std::iota(indices.begin(), indices.end(), 0);  std::sort(indices.begin(), indices.end(),            [&](int A, int B) -> bool {                 return Score[A] < Score[B];             }); 

Now indices can be used to index Names and Scores in the desired sorted order.

like image 133
wcochran Avatar answered Oct 10 '22 10:10

wcochran


As already suggested in other answers: Combining the name and the score of each individual is likely the simplest solution.

Generically, this can be achieved with what is sometimes referred to as a "zip" operation: Combining two vectors into a vector of pairs - along with a corresponding "unzip".

Implemented generically, this may look as follows:

#include <vector> #include <string> #include <algorithm> #include <iostream> #include <iterator>  // Fill the zipped vector with pairs consisting of the // corresponding elements of a and b. (This assumes  // that the vectors have equal length) template <typename A, typename B> void zip(     const std::vector<A> &a,      const std::vector<B> &b,      std::vector<std::pair<A,B>> &zipped) {     for(size_t i=0; i<a.size(); ++i)     {         zipped.push_back(std::make_pair(a[i], b[i]));     } }  // Write the first and second element of the pairs in  // the given zipped vector into a and b. (This assumes  // that the vectors have equal length) template <typename A, typename B> void unzip(     const std::vector<std::pair<A, B>> &zipped,      std::vector<A> &a,      std::vector<B> &b) {     for(size_t i=0; i<a.size(); i++)     {         a[i] = zipped[i].first;         b[i] = zipped[i].second;     } }   int main(int argc, char* argv[]) {     std::vector<std::string> names {"Karl", "Martin", "Paul", "Jennie"};     std::vector<int> score {45, 5, 14, 24};      // Zip the vectors together     std::vector<std::pair<std::string,int>> zipped;     zip(names, score, zipped);      // Sort the vector of pairs     std::sort(std::begin(zipped), std::end(zipped),          [&](const auto& a, const auto& b)         {             return a.second > b.second;         });      // Write the sorted pairs back to the original vectors     unzip(zipped, names, score);      for(size_t i=0; i<names.size(); i++)     {         std::cout << names[i] << " : " << score[i] << std::endl;     }     return 0; } 
like image 45
Marco13 Avatar answered Oct 10 '22 12:10

Marco13