Reputation: 23
I had code that was similar to this in Java, but getting it to work in C++ is a different story. Currently, this function does find the key correctly and pushes the key to the back of my vector. I would like to grab both the key and its pair of values to all be inserted into the same index of the vector. I have looked into using a pair for my vector so it would be (key, pair of values), which I am not sure I am able to do.
vector<string> getIfPresentPartOfSpeech(multimap<string, pair<string, string>> dictionary, string name) {
vector<string> response;
auto it = dictionary.begin();
while (it != dictionary.end()) {
// Check if value of this entry matches with given value
if (it->second.first == name) {
// Yes found
// Push the key in given map
response.push_back(it->first);
}
// Go to next entry in map
it++;
}
return response;
}
Upvotes: 0
Views: 463
Reputation: 1184
You can use std::copy_if
in <algorithm>
without having to write an explicit loop manually. Also pass dictionary
by (constant) reference to avoid unnecessary copy:
#include <algorithm>
#include <map>
#include <utility>
#include <vector>
// You'll need C++14 to use `auto const& kv` in your lambda expression
std::vector<std::pair<const std::string, std::pair<std::string, std::string>>>
getIfPresentPartOfSpeech(
const std::multimap<std::string, std::pair<std::string, std::string>>&
dictionary,
const std::string& name)
{
std::vector<
std::pair<const std::string, std::pair<std::string, std::string>>>
res;
std::copy_if(begin(dictionary), end(dictionary), std::back_inserter(res),
[&](auto const& kv) { return kv.second.first == name; });
return res;
}
//test
int main()
{
std::multimap<std::string, std::pair<std::string, std::string>> dictionary{
{"first", {"abc", "def"}},
{"second", {"123", "456"}},
{"first", {"asdf", "fdas"}},
{"thrid", {"abc", "123"}},
};
auto res = getIfPresentPartOfSpeech(dictionary, "abc");
for (auto& x : res)
std::cout << x.first << " " << x.second.first << " " << x.second.second
<< "\n";
}
Using a struct like @aep suggested would be much clearer. You'll need an extra conversion constructor for it to work with std::copy_if
:
struct Response {
std::string key;
std::pair<std::string, std::string> value;
// Provide a conversion constructor that convert your `dictionary` multimap
// key-value pair into a Response object
Response(const std::pair<const std::string,
std::pair<std::string, std::string>>& kv)
: key{kv.first}, value{kv.second}
{}
};
std::vector<Response> getIfPresentPartOfSpeech(
const std::multimap<std::string, std::pair<std::string, std::string>>&
dictionary,
const std::string& name)
{
std::vector<Response> res;
std::copy_if(begin(dictionary), end(dictionary), std::back_inserter(res),
[&](auto const& kv) { return kv.second.first == name; });
return res;
}
Upvotes: 1
Reputation: 1675
Define a struct for your response
and return a std::vector
of that type.
struct Response {
std::string key;
std::pair<std::string, std::string> resp_pair;
};
vector<Response> getIfPresentPartOfSpeech(multimap<string, pair<string, string>> dictionary, string name) {
vector<Response> response;
auto it = dictionary.begin();
while (it != dictionary.end()) {
// Check if value of this entry matches with given value
if (it->second.first == name) {
// Yes found
// Create a Response object
Response resp;
resp.key = it->first;
resp.resp_pair = it->second;
// Push it in the vector
response.push_back(resp);
}
// Go to next entry in map
it++;
}
return response;
}
It's further possible optimize this by using emplace_back
instead of push_back
to avoid multiple copies of the container element passing around.
Upvotes: 2