3

I am planning to organize some data using this type: std::unordered_map<std::string,std::vector<double>> which nicely represents a table with a variable number of dynamically named columns and a variable number of rows (vectors will always have the same size by construction).

A requirement is the possibility to sort the table with respect to a column, this mean: sort a vector in the map applying the same swaps also to all other vectors. It is not very hard to write a crappy algorithm to do this, but what about employing the great power of stl? Is there a way to do this? Changing data type is not a problem as long as the flexibility requirements are met.

Kerrek SB
  • 464,522
  • 92
  • 875
  • 1,084
DarioP
  • 5,377
  • 1
  • 33
  • 52
  • possible duplicate of [How do I sort a std::vector by the values of a different std::vector?](http://stackoverflow.com/questions/236172/how-do-i-sort-a-stdvector-by-the-values-of-a-different-stdvector) – Cubbi Aug 13 '13 at 14:28
  • Use [`std::sort`](http://en.cppreference.com/w/cpp/algorithm/sort) with a compare function which checks the keys? Or just use `std::map` which is sorted by key already? – Some programmer dude Aug 13 '13 at 14:28
  • @Cubbi The questions are similar, but I accept to organize the data differently if this can help the algorithm. I keep thinking about `tuple` but I can't figure out how to apply them... – DarioP Aug 13 '13 at 14:43
  • There isn't a single ready-made algorithm for this in the standard library, but you should be able to write something sensible with a single call of `std::sort` along with a custom comparator. – Kerrek SB Mar 02 '14 at 12:30

1 Answers1

0

You could create a special iterator that acted as a iterator over an array of the corresponding elements to the vector you are sorting by. You will have to create your own reference type as is the case in std::vector. You are going to want to make sure you get move semantics (assuming you are using a modern compiler) right as this will require a whole array of items to be moved and you really don't want that to mean a copy IMO. Assignment for this reference type would iterate over a row of the different vectors, assigning the corresponding value from the other reference's row to the new one.

class my_refrence_type {
private:
    //special refrence to know which vector you are sorting by
    std::vector<double>& ref_vec;
    //refrence so you can get an iterator from the map to preform assignment
    std::unordered_map<std::string,std::vector<double>>& map;
    //a location in the vectors. this is the row number
    int loc;
public:
   /* insert constructors here and other blah blah blah*/
   my_refrence_type& operator=(my_refrence_type&& x) {
      for(auto& vec : map) {
          vec.second[loc] = std::move(vec.second[x.loc]);
      }
   }
   //a method to get the reference vector's value so you can create a comparison function 
   double& get_ref_value() {
       return ref_vec[loc];
   }
};

So to recap, you need a special reference type that can treat a row across vectors as a single object and an iterator type over these rows. If you get that right sorting should work with plain old std::sort. It will also give you an interesting view over the vectors that might come in handy elsewhere.

Jake
  • 747
  • 1
  • 5
  • 19