Get Index of Minimum Element in TObjArray

I have a TObjArray stored in a TFile with kSingleKey set. The TObjArray stores a bunch of TH1D in a particular order.

Now I want to write a script that opens the TFile, gets the TObjArray, loops over the histograms contained therein, and returns the index of the histogram with the minimum value returned from some function. This is equivalent to e.g. get the index of the histogram with the smallest mean stored in the TObjArray.

I am trying to do this using a mixture of modern C++ algorithms and ROOT classes, so maybe that’s why I’m confused. Here’s my code:

  class LikelihoodInfo
  {
  public:
    LikelihoodInfo(TString fname)
    {
      TFile f(fname,"READ");
      toa = (TObjArray*)f.Get("toa");
      ranges = (TVectorD*)f.Get("ranges");  
    };

    TIter get_nll(const std::vector<int> & clusters)
    {
        auto nllcompare = [&clusters](const TObject* h1, const TObject* h2)->bool{
          return nll(clusters,(TH1D*)h1) < nll(clusters,(TH1D*)h2); // nll is a static function 
        };
        auto min_e = std::min_element(std::begin(*toa),std::end(*toa),nllcompare);
        return min_e;
    };
  private:
    TObjArray * toa;
    TVectorD * ranges;
  };

The current code compiles, but it only returns a TIter pointing to the histogram with the minimum nll. I need the index of that histogram in the TObjArray so I can then look up the corresponding range in the TVectorD. Is there a way to get the index without looping over the TObjArray twice? (once to get min_element, once to get the index)?

Note: I tried using std::distance(*toa,min_e) and toa->begin()-min_e like I would use for a std::vector but both fail to compile.

Jean-François

Hi Jean-François,

unfortunately there is no functionality yet to avoid the second loop. It is on our todo-list now to add that missing feature:
https://sft.its.cern.ch/jira/browse/ROOT-7123

The fastest way for you at the moment would be to code up the entire minimum search yourself and store the index while searching. The search itself is probably slower than std::min_element, but this avoids the second looping.

Hope that helps,
Benedikt

Thanks, I’ll have to benchmark to see which is faster in my case.

Jean-François