Reputation: 493
My program is based around a set of pairs, namely
typedef std::pair<int,int> innerPair;
typedef std::pair<innerPair,int> setElement;
std::set<setElement> Foo;
The innerPair
element is what really defines the setElement, but I need to attach a group ID to every element, hence the latter setElement
definition.
In the remainder of the program, I need to find innerPair
regardless of their group ID so I basically need a function
std::set<setElement>::iterator find(innePair);
that will find the innerPair regardless of its group ID. As it stands I could simply cycle through all available group ID and do multiple find() calls, but it is far from efficient.
Is there a concise way of defining a find( ... )
member function that perform some sort of wildcarded search, or do I need to overload it with my own definition?
Upvotes: 2
Views: 950
Reputation: 14750
You could use a multiset
, with a custom comparison function, or functor for instance:
struct innerPairCompare
{
bool operator () (const setElement &a, const setElement &b)
{
const innerPair &a_ = a.first;
const innerPair &b_ = b.first;
return (a_.first > b_.first || a_.first = b_.first && a_.second > b_.second);
}
};
then use it for your multiset
:
std::multiset<setElement,innerPairCompare> Foo;
It will store all the setElement
s with the same innerPair
in the same list.
Alternatively, if you need all the innerPair
with a given GroupID
, use a function comparing on groupID.
Finally, if you don't really need to keep the GroupID
and the innerPair
together, you could use a map
(or multimap
), using the GroupID
or the innerPair
as the Key
.
Upvotes: 1
Reputation: 74118
If you have multiple elements with the same inner pair and a differing group id, you could use std::multimap<innerPair, int>
.
This allows you to store multiple elements with the same innerPair
.
It also simplifies searching with lower_bound/upper_bound
or equal_range
.
Upvotes: 3
Reputation: 154045
If you want to search by a partial object, you are probably best off not to use a std::set<...>
but rather a std::map<...>
:
std::map<std::pair<int, int>, int>
This has nearly the value type you targeted for your std::set<...>
anyway (the difference is that the first
member is declared to be const
).
If you really insist in using a std::set<...>
you'd needto create a comparator type which ignores the last second
member. I'm not sure if std::set<...>
supports mixed type comparisons (I think it does not).
Upvotes: 2
Reputation: 110778
I see two possible designs for this. One may be more applicable than the other.
It may be more appropriate for innerPair
to be a struct with 3 members (first, second, and group ID) or an std::tuple<int, int, int>
. Is the group ID part of the innerPair
objects? If so, then I suggest this is the better design.
If not (and to be honest, I think in your situation it's not), you should be using an std::map<innerPair,int>
to create a mapping from innerPair
objects to group IDs. You can then find an element easily with:
std::map<innerPair,int> mapping;
// Fill your map
innerPair key = {1, 2};
auto found_iter = mapping.find(key);
You can also get the group ID for a specific innerPair
with:
int group_id = mapping[key];
You don't need to provide a custom comparator because operator<
is already defined for std::pair
.
Upvotes: 2
Reputation: 133669
If you want to keep using an std::set
then you can use std::find_if
with a custom predicate, take a look at this answer.
Basically you will define a function
bool pairCorresponds(std::pair<int,int> element)
that will do the work for you.
Upvotes: 0