yedolte
yedolte

Reputation: 19

C++ using std::find in a map where the key is a custom class

I'm a C++ newbie and I've been struggling with this for the last couple of days. I have a task where I need to create a map(unordered or multitable not allowed). 1. Key for the map has to be a class SportTeam and it should have a string country and a string sportsDiscipline. 2. The value for each key is a vector of strings. 3. After creating the map I should use STL find function to check if any of the keys have Poland as a country.

Here is how I created the map:

SportTeam team1{"USA", "Hockey"}, 
team2{"Poland", "Volleyball"}, 
team3{"France", "Running"},
team4{"China", "Swimming"}, 
team5{"Poland","Tennis"};
using  mapVector = std::vector<std::string>;
std::map<SportTeam,mapVector> mapOfTeams;
mapOfTeams[team1].emplace_back("Team Beavers");
mapOfTeams[team2].emplace_back("Team Badgers");
mapOfTeams[team3].emplace_back("Team Snails");
mapOfTeams[team4].emplace_back("Team Doggos");
mapOfTeams[team5].emplace_back("Team Pinguins");

This is my header file:

class SportTeam {
public:
std::string country;
std::string sportsDiscipline;

SportTeam(std::string newCountry, std::string 
newDiscipline) :
country{std::move(newCountry)},
sportsDiscipline{std::move(newDiscipline)}
{};

bool operator <(const SportTeam& other)const{
    return country < other.country || (country == 
other.country && sportsDiscipline < 
other.sportsDiscipline);
}
};

The problem is I have no idea how can I check the class members with find function. I was able to find country when accessing iterator like this

mapIt->first.country

and then comparing it in if statement in the iterator loop however I cannot replicate this with find function.

I tried following the cpp reference guide for std::find that suggests something like this:

auto search = example.find(2);
if (search != example.end()){
...}

but it doesn't work if I try it on map itself since it doesn't recognize "Poland". I tried different syntax combinations but the only way I was able to access the country member was when I tried this:

auto mapIt = mapOfTeams.begin();
auto search = 
mapIt->first.country.find("Poland");

This option doesn't let me compare the result with mapOfTeam.end() as cpp reference suggests as it throws an error for != saying it's an invalid operand.

Any help will be appreciated. I spent quite a long time on stack and other forums but I wasn't able to find solution to my issue hence I decided to gather up my courage and write my first post here :)

TL;DR Key is a class with 2 members (country and sportsDiscipline). I have to use map::find function to check if country = "Poland" and I can't make it work.

Upvotes: 1

Views: 4379

Answers (2)

Sitesh
Sitesh

Reputation: 1878

You need std::find_if or std::any_of where you can have UnaryPredicate (or lambda function) to give your comparison logic.

Plenty of examples are available over the internet on how to use this algorithms.

Upvotes: 0

xaxxon
xaxxon

Reputation: 19801

mapOfTeams.find(SportTeam("Poland", "Volleyball"));

works.

https://godbolt.org/z/K0Akq6

You have to create an object of the key type in order to compare the keys. You can't construct a SportTeam object based just on a country name, since you require both a country name and discipline.

In order to use a map/hash/dictionary/associative-array efficiently you need to make sure to key them by the thing you want to look them up by. If you want to look it up by something different (country only), then you'll need to iterate through all the entries searching the country - which is less efficient.

for(auto const & sports_team : mapOfTeams) {
  if (sports_team.first.country == "Poland") {
    // do whatever with match
  }
}

Or as others have suggested, you can do a find_if with a custom comparator, but that's essentially the same code as what I put above - and still not making use of the efficiency of a lookup in a map.

Upvotes: 1

Related Questions