Vectors, structs and std::find

67,198

Solution 1

std::find_if:

it = std::find_if(bot.monsters.begin(), bot.monsters.end(), 
        boost::bind(&monster::id, _1) == currentMonster);

Or write your own function object if you don't have boost. Would look like this

struct find_id : std::unary_function<monster, bool> {
    DWORD id;
    find_id(DWORD id):id(id) { }
    bool operator()(monster const& m) const {
        return m.id == id;
    }
};

it = std::find_if(bot.monsters.begin(), bot.monsters.end(), 
         find_id(currentMonster));

Solution 2

You need to write your own search predicate:

struct find_monster
{
    DWORD id;
    find_monster(DWORD id) : id(id) {}
    bool operator () ( const monster& m ) const
    {
        return m.id == id;
    }
};

it = std::find_if( monsters.begin(), monsters.end(), find_monster(monsterID));

Solution 3

Take a look at the std::find template, the third parameter especially:

template<class InputIterator, class EqualityComparable>
InputIterator find(InputIterator first, InputIterator last,
               const EqualityComparable& value);

What is this EqualityComparable? Again from the documentation:

A type is EqualityComparable if objects of that type can be 
compared for equality using operator==, and if operator== is 
an equivalence relation. 

Now, your type monster needs to define such an operator. If you don't the compiler generates one for you (as also the default ctor and the dtor) which does a memcmp sort of thing which doesn't work in your case. So, to use std::find first define a comparator function/functor that the algorithm can use to match your currentMonster i.e. something along the lines of:

 struct monster {
  // members
  bool operator==(const monster& l, const monster& r) const
  {
     return l.id == r.id;
  }
 };

Solution 4

or put the monsters in a map instead of a vector

or if they must be in a vector create an index map ie map of ID to vector index

Share:
67,198
liliumdev
Author by

liliumdev

Updated on September 18, 2020

Comments

  • liliumdev
    liliumdev over 3 years

    Again me with vectors. I hope I'm not too annoying. I have a struct like this :

    struct monster 
    {
        DWORD id;
        int x;
        int y;
        int distance;
        int HP;
    };
    

    So I created a vector :

    std::vector<monster> monsters;
    

    But now I don't know how to search through the vector. I want to find an ID of the monster inside the vector.

    DWORD monster = 0xFFFAAA;
    it = std::find(bot.monsters.begin(), bot.monsters.end(), currentMonster);
    

    But obviously it doesn't work. I want to iterate only through the .id element of the struct, and I don't know how to do that. Help is greatly appreciated. Thanks !

  • Martin Sherburn
    Martin Sherburn over 11 years
    Nice answer, but there is a typo in the constructor. It should be ':' not ';'
  • Christian Rau
    Christian Rau over 11 years
    In addition to writing your own search predicate, you need to use std::find_if instead of std::find.
  • Kyle Heuton
    Kyle Heuton about 11 years
    Does this work? I did not have success because an operator definition inside a struct can only have 1 input
  • H'H
    H'H over 9 years
    using boost, Perfect!
  • Tomáš Zato
    Tomáš Zato over 8 years
    I wonder, if I have {int, int}, could I cast it to long and use normal find then?
  • Tomáš Zato
    Tomáš Zato over 8 years
    Same problem as Snoozer. -1, please complete the answer.
  • Semjon Mössinger
    Semjon Mössinger over 8 years
    What is the meaning of "bot" in bot.monsters.begin()?
  • nathan
    nathan over 7 years
    What is the datatype if "it"??
  • tomereli
    tomereli about 6 years
    good thing you gave an example without boost - we never use boost in embedded systems, it is huge. I just didn't understand why you inherited the functor object from std::unary_function - looks like it would work either way, won't it? appreciate your answer.
  • tomereli
    tomereli about 6 years
    @Hiyper - The type would be std::vector<monster>::iterator. Or you can use auto it = std::find_if... if you are using c++11
  • Johannes Schaub - litb
    Johannes Schaub - litb about 6 years
    @tomereli IIRC it wouldn't work without it in C++03, but I think it will in C++11, which can figure out the return type itself using decltype.
  • Adam Erickson
    Adam Erickson almost 6 years
    @SemjonMössinger This was not explicitly stated, but bot should be a struct containing the following vector of structs: std::vector<monster> monsters;
  • Darkproduct
    Darkproduct over 5 years
    unary_function is deprecated in C++11 and removed in C++17.
  • Tzunghsing David Wong
    Tzunghsing David Wong about 5 years
    the concept is correct. this works for me: bool operator==(const monster& r) const { return id == r.id; }
  • Mecanik
    Mecanik about 2 years
    How are you even compiling this? It fails on latest C++ and VS2019.