Std.max_element using cppyy/PyROOT

Dear experts,

I am trying to do something like the following c++ code (which runs in interactive c++ ROOT just fine) to find the index of the largest element in a std::vector:

std::vector<int>* x = new std::vector<int>({1,2,3});
std::max_element(x->begin(), x->end()) - x->begin()

But, I’d like to do that in python using cppyy. I tried this but it doesn’t seem to work:

from cppyy.gbl import std
x = std.vector[int]([1,2,3])
std.max_element(x.begin(), x.end())-x.begin()

I get this error message:

TypeError                                 Traceback (most recent call last)
<ipython-input-4-c46b26545120> in <module>
      1 from cppyy.gbl import std
      2 x = std.vector[int]([1,2,3])
----> 3 std.max_element(x.begin(), x.end())-x.begin()

TypeError: __gnu_cxx::__normal_iterator<int*,vector<int> > __gnu_cxx::__normal_iterator<int*,vector<int> >::operator-(long __n) =>
    TypeError: could not convert argument 1 (int/long conversion expects an integer object)

Is possible to use the max_element function in cppyy?

ROOT Version: 6.22/00
Python Version: Python 3.7.6
Platform: SLF 7.9 (Nitrogen)
Compiler: clang 10.0.0-62e61


It does not seem a problem in std::max_element, it looks like an issue in the operator- of the iterator.

You can bypass that by dereferencing the iterators and then doing a subtraction operation with integers.

std.max_element(x.begin(), x.end()).__deref__() - x.begin().__deref__()

Edit: I initially thought @etejedor’s suggestion was the solution, but unfortunately (due to the example being a little confusing) it did not turn out to do what I wanted. I will make a fresh post below to show what the issue is.

To follow up, the suggestion @etejedor made above seems to have some weird behavior. For example, in interactive python, it gives a weird result for std::vectors of floats:

jhakala@cmslpc154 ~ # python -i
Python 3.7.6 (default, Aug 12 2020, 18:59:21)
[Clang 10.0.0 ] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> from cppyy.gbl import std
>>> def getIndexOfMax(v):
...   return std.max_element(v.begin(), v.end()).__deref__() - v.begin().__deref__()
>>> vi = std.vector[int]([7,8,9])
>>> getIndexOfMax(vi)
>>> vf = std.vector[float]([7.,8.,9.])
>>> getIndexOfMax(vf)

That last result seems very strange to me. Other times I’ve tried this it gives different weird results, such as returning the value of the max element, rather than the index (which is what I want).

If I do this in c++ interactive ROOT, things seem to work fine with float vectors:

root [0] std::vector<float>* x = new std::vector<float>({7., 8., 9.})
(std::vector<float> *) 0xbac7a0
root [1] std::max_element(x->begin(), x->end()) - x->begin()
(long) 2

So I wonder how one might get that kind of behavior reliably with cppyy.

Right! We want the index.

I believe we can use std::distance for that:

def getIndexOfMax(v):
   return std.distance(v.begin(), std.max_element(v.begin(), v.end()))

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