Hafiz Al Masud Ovi
Hafiz Al Masud Ovi

Reputation: 53

How to Construct a vector of Tuples and Sort them like Pair?

Suppose, I have several integer elements like this:

(3 9 1), (1 5 2), (2 8 3), (1 4 4), (1 6 5), (1 5 6)

Now I want to sort the elements like vector of pairs are sorted. Only difference is that instead of 2 keys we have 3 keys here. After sorting the elements will look like:

(1 4 4), (1 5 2), (1 5 6), (1 6 5), (2 8 3), (3 9 1)

Is there any STL or other techniques to achieve this? I found out about Tuples but having some problems to understand this well.
Can you guys help me in any way please? May be by providing useful links or Explaining the process.

Upvotes: 5

Views: 3563

Answers (2)

Matt
Matt

Reputation: 2802

A vector of tuple can be sorted using nothing but STL if you want.

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

int main(int argc, char * argv[]){

    std::vector< std::tuple<int, int, int> > myVec;

    myVec.emplace_back(3, 9, 1);
    myVec.emplace_back(1, 5, 2);
    myVec.emplace_back(2, 8, 3);
    myVec.emplace_back(1, 4, 4);
    myVec.emplace_back(1, 6, 5);
    myVec.emplace_back(1, 5, 6);

    std::sort(myVec.begin(), myVec.end());

    for (auto i : myVec){
        std::cout << std::get<0>(i) << ", " << std::get<1>(i) << ", " << std::get<2>(i) << '\n';
    }

    return 0;
}

This is the example from here just modified with your values.

How it works is a new tuple is constructed with emplace_back and added to the end of the vector. You could use push_back(std::make_tuple(... if you want but that seems overly complicated. Then you sort the vector as you would any other vector. The default behavior of sort is ascending. You can change the behavior of sort by adding you own comp. The arguments of your comparing function will be 2 tuples. The return type is the boolean result of your comparison. Since tuples have all the comparisons (<,>, <=,etc) already, you don't need to redefine them. You can use this to compare dissimilar things as well, it just gets more complicated.

bool myFunction(const std::tuple<int, int, int> &i, const std::tuple<int, int, int> &j) {
    return i > j;
}

....
std::sort(myVec.begin(), myVec.end(), myFunction);
....

And this will sort the vector in descending order. You can replace myFunction with a lambda as well.

std::sort(myVec.begin(), myVec.end(), [](const std::tuple<int, int, int> &i, const std::tuple<int, int, int> &j) {
    return i > j;
});

Upvotes: 7

Henrique Jung
Henrique Jung

Reputation: 1498

I propose two solutions: the first using a custom structure using a custom < operator that uses std::tie to compare the three integers in order, and the second using std::tuple.

#include <iostream>
#include <set>
#include <vector>

struct three_integers {
  int a, b, c;
  bool operator<(const three_integers &other) const {
    return std::tie(a, b, c) < std::tie(other.a, other.b, other.c);
  }
};

int main(int argc, char *argv[]) {

  // 1st solution using a custom structure
  // std::set containers are always ordered according to the < operator
  std::set<three_integers> sorted_set = {{3, 9, 1}, {1, 5, 2}, {2, 8, 3},
                                         {1, 4, 4}, {1, 6, 5}, {1, 5, 6}};

  std::cout << "Sorted set:\n";
  for (auto &element : sorted_set) {
    std::cout << "(" << element.a << " " << element.b << " " << element.c << ")"
              << std::endl;
  }

  std::vector<three_integers> sorted_vector = {{3, 9, 1}, {1, 5, 2}, {2, 8, 3},
                                               {1, 4, 4}, {1, 6, 5}, {1, 5, 6}};

  // std::vector is not ordered, so we call std::sort on it to make it just like
  // std::set, it will use our custom < operator
  std::sort(sorted_vector.begin(), sorted_vector.end());

  std::cout << "Sorted vector:\n";
  for (auto &element : sorted_vector) {
    std::cout << "(" << element.a << " " << element.b << " " << element.c << ")"
              << std::endl;
  }

  // 2nd solution using tuples
  std::vector<std::tuple<int, int, int>> sorted_vector_tuple = {
      {3, 9, 1}, {1, 5, 2}, {2, 8, 3}, {1, 4, 4}, {1, 6, 5}, {1, 5, 6}};

  std::sort(sorted_vector_tuple.begin(), sorted_vector_tuple.end());

  std::cout << "Sorted vector of tuples:\n";
  for (auto &element : sorted_vector_tuple) {
    std::cout << "(" << std::get<0>(element) << " " << std::get<1>(element)
              << " " << std::get<2>(element) << ")" << std::endl;
  }

  return 0;
}

Output

Sorted set:
(1 4 4)
(1 5 2)
(1 5 6)
(1 6 5)
(2 8 3)
(3 9 1)
Sorted vector:
(1 4 4)
(1 5 2)
(1 5 6)
(1 6 5)
(2 8 3)
(3 9 1)
Sorted vector of tuples:
(1 4 4)
(1 5 2)
(1 5 6)
(1 6 5)
(2 8 3)
(3 9 1)

I recommend you to read the std::sort documentation.

Upvotes: 1

Related Questions