Sort struct-of-array format with RVec

I am using RDataFrame, and I have RVecs containing various jet variables. I need to work with the 4 highest pT jets, so I need to sort these by the jet pT. How can I do this easily (preferably without having to define a new column containing vectors of structs)?


ROOT Version: 6.14
Platform: LCG dev4


You may try using something like std::nth_element, to avoid sorting the whole vector. Here is an example:

#include <iostream>
#include <vector>
#include <algorithm>
#include <functional>

int main()
{
	std::vector<int> v{5, 6, 4, 3, 22, 15, 7, 9, 3};
	std::nth_element(v.begin(), v.begin()+4, v.end(), std::greater<int>());
	std::cout << "The four largest elements are " 
             << v[0] << ", " << v[1] << ", " << v[2] << ", " << v[3] << '\n';
	return 0;
}

This program gives me the following output:

The four largest elements are 9, 22, 15, 7

It’s not that sorting is inefficient, it’s that I have to rearrange the other vectors according to the order the pT vector got sorted.

I haven’t found anything in either the standard library or range-v3 that would easily help. The best solution I have now is to use range-v3’s zipWith to turn it into a vector of structs, then sort that.

It’s not that sorting is inefficient, it’s that I have to rearrange the other vectors according to the order the pT vector got sorted.

In that case you can use std::sort with a custom function to get the indices in the order you want, then you can just apply the sorting to the other vectors.

Maybe this example will help a bit:

#include <algorithm>
#include <numeric>
#include <iostream>
#include <vector>

template<typename T>
inline std::vector<size_t> index_sort(const std::vector<T> &v)
{
   std::vector<size_t> idx(v.size());
   std::iota(idx.begin(), idx.end(), size_t{});
   std::sort(idx.begin(), idx.end(), [&v](const size_t& i, const size_t& j) { return v[i] < v[j]; });
   return idx;
}

template<typename T>
void permute(std::vector<T>& v, std::vector<typename std::vector<T>::size_type>&& idx)
{
   std::vector<T> tmp = v;
   auto it = v.begin();
   for (auto& i : idx)
      *it++ = tmp[i];
}

int main()
{
   std::vector<int> v = {9, 6, 3, 5, 2, 4, 1, 8, 7, 0};

   permute(v, index_sort(v));

   for (auto i : v)
      std::cout << i << " ";
   std::cout << std::endl;

   return 0;
}

It gives the following output:

0 1 2 3 4 5 6 7 8 9

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.