I have a vector with doubles which I want to rank (actually it's a vector with objects with a double member called costs). If there are only unique values or I ignore the nonunique values then there is no problem. However, I want to use the average rank for nonunique values. Furthermore, I have found some question at SO about ranks, however they ignore the non-unique values.
Example, say we have (1, 5, 4, 5, 5) then the corresponding ranks should be (1, 4, 2, 4, 4). When we ignore the non-unique values the ranks are (1, 3, 2, 4, 5).
When ignoring the nonunique values I used the following:
void Population::create_ranks_costs(vector<Solution> &pop)
{
  size_t const n = pop.size();
  // Create an index vector
  vector<size_t> index(n);
  iota(begin(index), end(index), 0);
  sort(begin(index), end(index), 
       [&pop] (size_t idx, size_t idy) { 
         return pop[idx].costs() < pop[idy].costs();
       });
  // Store the result in the corresponding solutions
  for (size_t idx = 0; idx < n; ++idx)
    pop[index[idx]].set_rank_costs(idx + 1);
}
Does anyone know how to take the non-unique values into account? I prefer using std::algorithm since IMO this lead to clean code.
                        
One way to do so would be using a
multimap.Place the items in a multimap mapping your objects to
size_ts (the intial values are unimportant). You can do this with one line (use the ctor that takes iterators).Loop (either plainly or using whatever from
algorithm) and assign 0, 1, ... as the values.Loop over the distinct keys. For each distinct key, call
equal_rangefor the key, and set its values to the average (again, you can use stuff fromalgorithmfor this).The overall complexity should be Theta(n log(n)), where n is the length of the vector.