1

I am using C++ and i have 2 vectors that a related to each other:

vector<double> val = {.3,.5,.2,.4};
vector<string> str = {'a','b','c','d'};

I would like to search val for the max, and then return the string from str in the same position:

vector<double>::const_iterator it;
it = max_element(val.begin(), val.end());

So, how can i use it inside str to get the letter?

string lettter;
letter = str.at(it-> ????? );

Thank!!!

KevinCameron1337
  • 517
  • 2
  • 8
  • 16

4 Answers4

4

How about

letter = str.at(it - val.begin());

?

(Rationale)

Community
  • 1
  • 1
  • I think `std::distance` is slightly better because it will work with lists and other containers. The rationale you link doesn't really apply here because `max_element` is already O(n) so adding another possibly O(n) operation won't matter that much. – interjay Feb 05 '13 at 20:09
  • Lots of good answers, i ended up going with the distance() answer. So it seemed fair to give that answer the nod. Wish i could accept 2 :) – KevinCameron1337 Feb 05 '13 at 20:38
3

You can find out how far it is from the beginning of val and then use that to index str:

str[std::distance(std::begin(val), it)]

By using std::distance, this will still work if you change the type of val to a container whose iterator does not provide random access. However, when using it on a random access iterator, you will still get constant time complexity. Using std::begin allows you to change val to an C-style array if you ever wanted to.

It's worth mentioning that you should be initialising str with:

vector<string> str = {"a","b","c","d"};

std::string has no constructor that takes a char.

Joseph Mansfield
  • 108,238
  • 20
  • 242
  • 324
  • i see an error that says "No instance of function template std::distance matches the argument list" ------ I tried `str[std::distance(std::begin(val), *it)]` same thing – KevinCameron1337 Feb 05 '13 at 20:33
  • @Special--k I think your problem is that `it` is a `const_iterator` while `std::begin` gives an `iterator`. Unfortunately, there is no `std::cbegin` (an oversight in the standard). You can either make `it` an `iterator` or implement `cbegin` yourself. Or you could just use `val.cbegin()` instead of `std::begin(val)`. – Joseph Mansfield Feb 05 '13 at 20:48
2

Get the index of the element like so:

auto index = std::distance(val.begin(), it);

Then index into your string array:

auto letter = str[index];

Note that if these values are correlated, you should probably forcibly keep them together:

typedef std::pair<double, string> valstr_pair;
std::vector<valstr_pair> valstr;

auto it = std::max_element(valstr.begin(), valstr.end(),
    [](const valstr_pair& first, const valstr_pair& second)
    {
        return first.first < second.first; // compare values
    });

it->first;  // max value
it->second; // string of max value
GManNickG
  • 494,350
  • 52
  • 494
  • 543
  • Its a good idea, but i would then just use a map. The problem is that my vectors are filled up at different times in my application. That is not evident in my simple example above. So, i cannot keep the values together because at the time the strings (Files names) are inserted into their vector, the doubles (a score function) has no been run. I guess i could insert the files names with all 0's and then just update them once the score is calculated. – KevinCameron1337 Feb 05 '13 at 20:21
2

This will give you the distance between the iterator returned by max_element() and the beginning of the vector:

std::distance(val.begin(), it).

You can then use it as an index into str.

Andy Prowl
  • 124,023
  • 23
  • 387
  • 451