docco cobai
docco cobai

Reputation: 21

Any way to compare many ways in data structure in C++

For example I have struct

struct A {
std::string Id;
std::string Name;
Std::string Year;
};

I defined data type look like
std::map<A, int> MyMap;

I put some item to MyMap. I want to find an item that satisfy one of below

- MyMap.find(it1); //that return iter if match Id
- MyMap.find(it2); //that return iter if match both Id and Name
- MyMap.find(it3); //that return iter if match all Id, Name,Year

I know I must define operator< in struct A but how to define that work with 3 cases above. Or Which data type instead of Map is suitable in this case.

Upvotes: 1

Views: 94

Answers (2)

Jarod42
Jarod42

Reputation: 217398

If your research is still in same order, you might use something like:

struct A {
    std::string Id;
    std::string Name;
    Std::string Year;
};

bool operator < (const A& lhs, const A& rhs) {
    return std::tie(lhs.Id, lhs.Name, lhs.Year) < std::tie(rhs.Id, rhs.Name, rhs.Year);
}


auto findById(const std::map<A, int>&m, const std::string& id)
{
    auto it = m.lower_bound(A{id, "", ""});

    if (it != m.end() && it->first.Id == id) {
        return it;
    }
    return m.end();
}

auto findByIdName(const std::map<A, int>&m, const std::string& id, const std::string& name)
{
    auto it = m.lower_bound(A{id, name, ""});

    if (it != m.end() && it->first.Id == id && it->first.Name == name) {
        return it;
    }
    return m.end();

}

auto findByIdNameYear(const std::map<A, int>&m,
                      const std::string& id,
                      const std::string& name,
                      const std::string& year)
{
    return m.find(A{id, name, year});
}

If you prefer to use std::vector, you may use std::find_if like that:

std::vector<A> as = /*...*/;
auto it = std::find_if(as.begin(), as.end(),
                       [&](const A& a){ return a.Id = id && a.Name = name;} );
if (it == as.end()) {
    // Not found
} else {
    // use *it as matching A.
}

Upvotes: 0

eerorika
eerorika

Reputation: 238361

std::map can only have one predicate for associating key with a value.

You can use different predicates with the standard algorithm std::find_if to achieve this, but it does a linear search, rather than an efficient map lookup.

If you need multiple predicates to look up an element efficiently, then you need a multi-index container. The standard library does not have such a thing, but you can implement one by using multiple maps internally, or you can use a generic solution from Boost.

Upvotes: 4

Related Questions