473,508 Members | 2,133 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

Partial key match in a map

I have a map, with a composite key (a struct). I would like to delete
all the elements with a partial key match and may be do other things in
the future. The way I am doing it is as follows. I think this is not
very effecient. I am wondering is there a better way to do this

struct SLNetKey

{

string m_usrid;

string m_portfolio;

string m_symbol;

PorSide m_enSide;

bool operator = (const stLNetRowInfo *row);

};
typedef map<SLNetKey, SLNetData> MapLNet;

typedef map<SLNetKey, SLNetData>::iterator MapiterLNet;
class CLNetData

{

public:
int DelRowsByUser (const char *user);
private:
MapLNet m_Data;

};

int CLNetData::DelRowsByUser (const char *user)

{

MapiterLNet pREnditer = m_Data.end();

MapiterLNet pBeg = m_Data.end(), pEnd = m_Data.end();

string User = user;

bool bBeg = true;

for (MapiterLNet pRiter = m_Data.begin(); pRiter != pREnditer;
++pRiter) {

if (bBeg && pRiter->first.m_usrid == User)

{

bBeg = false;

pBeg = pRiter;

}

else if (!bBeg)

{

if (pRiter->first.m_usrid != User)

{

pEnd = pRiter;

break;

}

}

}

if (pBeg == m_Data.end())

return -1;

m_Data.erase (pBeg, pEnd);

return 0;

}

//Map comparator function, just for information
bool operator<(const SLNetKey& lhs, const SLNetKey& rhs)

{

if (lhs.m_usrid != rhs.m_usrid)

return lhs.m_usrid < rhs.m_usrid;

if (lhs.m_portfolio != rhs.m_portfolio)

return lhs.m_portfolio < rhs.m_portfolio;

if (lhs.m_symbol != rhs.m_symbol)

return lhs.m_symbol < rhs.m_symbol;

return (int)lhs.m_enSide < (int)rhs.m_enSide;

}

Oct 28 '05 #1
9 5607
Ninan wrote:
I have a map, with a composite key (a struct). I would like to delete
all the elements with a partial key match and may be do other things in
the future. The way I am doing it is as follows. I think this is not
very effecient. I am wondering is there a better way to do this

struct SLNetKey

{

string m_usrid;

string m_portfolio;

string m_symbol;

PorSide m_enSide;

bool operator = (const stLNetRowInfo *row);

};
typedef map<SLNetKey, SLNetData> MapLNet;

typedef map<SLNetKey, SLNetData>::iterator MapiterLNet;
class CLNetData

{

public:
int DelRowsByUser (const char *user);
private:
MapLNet m_Data;

};

int CLNetData::DelRowsByUser (const char *user)
You should make the argument a const string&, and it would
automatically do the conversion for you, making the variable User below
(which should be const, BTW) unnecessary.

{

MapiterLNet pREnditer = m_Data.end();
This line is likely premature optimization. If inlining is enabled,
there will most likely be no penalty for retrieving the iterator. If
you keep this, you should at least make it const.

MapiterLNet pBeg = m_Data.end(), pEnd = m_Data.end();

string User = user;

bool bBeg = true;

for (MapiterLNet pRiter = m_Data.begin(); pRiter != pREnditer;
++pRiter) {

if (bBeg && pRiter->first.m_usrid == User)

{

bBeg = false;

pBeg = pRiter;

}

else if (!bBeg)

{

if (pRiter->first.m_usrid != User)
There's no reason not to combine these two:

else if( !bBeg && pRiter->first.m_usrid != User )

{

pEnd = pRiter;

break;

}

}

}
It might be clearer if you had two loops, one to find pBegin and one to
find pEnd. This would eliminate the boolean bBeg and would make things
simpler.

if (pBeg == m_Data.end())

return -1;

m_Data.erase (pBeg, pEnd);

return 0;

How about returning the number of elements deleted instead? If not, how
about a bool instead of the more cryptic 0 or -1.


}
You could use an STL algorithm like find_if
(http://www.sgi.com/tech/stl/find_if.html) or possibly the second
version of equal_range (http://www.sgi.com/tech/stl/equal_range.html ;
n.b., the algorithm's requirements).

//Map comparator function, just for information
bool operator<(const SLNetKey& lhs, const SLNetKey& rhs)

{

if (lhs.m_usrid != rhs.m_usrid)

return lhs.m_usrid < rhs.m_usrid;

if (lhs.m_portfolio != rhs.m_portfolio)

return lhs.m_portfolio < rhs.m_portfolio;

if (lhs.m_symbol != rhs.m_symbol)

return lhs.m_symbol < rhs.m_symbol;

return (int)lhs.m_enSide < (int)rhs.m_enSide;

}


Cheers! --M

Oct 28 '05 #2
find_if and equal_range are for exact key matches, It won't work in
this case. I only know part of the key, ie m_usrid

Oct 28 '05 #3
Ninan wrote:
find_if and equal_range are for exact key matches, It won't work in
this case. I only know part of the key, ie m_usrid


Please quote the post you are replying to (on Google groups, select
"show options" and click "Reply" in the revealed header); it makes it
easier for others to follow the discussion and thus more likely that
they'll participate.

You can supply your own predicate and comparison functors to those two
functions, so they can be configured to do whatever you want.

Cheers! --M

Oct 28 '05 #4
TIT
Ninan sade:
I have a map, with a composite key (a struct). I would like to delete
all the elements with a partial key match and may be do other things in
the future. The way I am doing it is as follows. I think this is not
very effecient. I am wondering is there a better way to do this

<snip>

Here's possibly a more dynamic and expandable version:
(adjust it at your free will to std::maps)

#include <set>
#include <functional>

#define MULTIKEYDEF(NAME,TYPE) \
inline TYPE const & NAME() const { return d_##NAME; } \
inline void NAME(TYPE const & t) { d_##NAME = t; } \
TYPE d_##NAME; \
class T##NAME \
: public std::unary_function<Tmultikey*,bool> { \
private: \
TYPE d_compare; \
public: \
T##NAME(TYPE t) : d_compare(t) {} \
T##NAME(T##NAME const & self) \
: d_compare(self.d_compare) {} \
bool operator()(Tmultikey * mk) { \
return d_compare == mk->##NAME(); \
} \
}

class Tmultikey {
public:
// Actual keys
// Can be accessed through d_primary and d_secondary,
// or primary() and secondary()
MULTIKEYDEF(primary , unsigned int);
MULTIKEYDEF(secondary, unsigned int);

// Mandatory
bool operator < (Tmultikey const & mk) const {
if(primary() < mk.primary()) return true;
else if(primary() == mk.primary()) {
return secondary() < mk.secondary();
}
return false;
}

// Constructor
Tmultikey(unsigned int p, unsigned int s)
: d_primary(p), d_secondary(s) {}

// Eraser for std::set
template<typename Compare>
static void erase(std::set<Tmultikey> & c, Compare op) {
typename std::set<Tmultikey>::iterator pos = c.begin();
while(pos != c.end()) {
if(op(&(*pos))) {
c.erase(pos++);
} else ++pos;
}
}
};

int main(int argc, char* argv[])
{
std::set<Tmultikey> mkset;

mkset.insert(Tmultikey(1,5));
mkset.insert(Tmultikey(6,4));
mkset.insert(Tmultikey(3,7));
mkset.insert(Tmultikey(1,6));

Tmultikey::erase(mkset,Tmultikey::Tsecondary(4));
Tmultikey::erase(mkset,Tmultikey::Tprimary(1));

// If you have compose_f_gx_hx and siblings (non-standard functions)
// Removes keys where primary is 1 or secondary is 4
Tmultikey::erase(mkset, compose_f_gx_hx(
std::logical_or<bool>(),
Tmultikey::Tprimary(1),
Tmultikey::Tsecondary(4)));

return 0;
}

TIT
Oct 28 '05 #5

TIT wrote:
Ninan sade:
I have a map, with a composite key (a struct). I would like to delete
all the elements with a partial key match and may be do other things in
the future. The way I am doing it is as follows. I think this is not
very effecient. I am wondering is there a better way to do this

<snip>

Here's possibly a more dynamic and expandable version:
(adjust it at your free will to std::maps)

#include <set>
#include <functional>

#define MULTIKEYDEF(NAME,TYPE) \
inline TYPE const & NAME() const { return d_##NAME; } \
inline void NAME(TYPE const & t) { d_##NAME = t; } \
TYPE d_##NAME; \
class T##NAME \
: public std::unary_function<Tmultikey*,bool> { \
private: \
TYPE d_compare; \
public: \
T##NAME(TYPE t) : d_compare(t) {} \
T##NAME(T##NAME const & self) \
: d_compare(self.d_compare) {} \
bool operator()(Tmultikey * mk) { \
return d_compare == mk->##NAME(); \
} \
}

class Tmultikey {
public:
// Actual keys
// Can be accessed through d_primary and d_secondary,
// or primary() and secondary()
MULTIKEYDEF(primary , unsigned int);
MULTIKEYDEF(secondary, unsigned int);

// Mandatory
bool operator < (Tmultikey const & mk) const {
if(primary() < mk.primary()) return true;
else if(primary() == mk.primary()) {
return secondary() < mk.secondary();
}
return false;
}

// Constructor
Tmultikey(unsigned int p, unsigned int s)
: d_primary(p), d_secondary(s) {}

// Eraser for std::set
template<typename Compare>
static void erase(std::set<Tmultikey> & c, Compare op) {
typename std::set<Tmultikey>::iterator pos = c.begin();
while(pos != c.end()) {
if(op(&(*pos))) {
c.erase(pos++);
} else ++pos;
}
}
};

int main(int argc, char* argv[])
{
std::set<Tmultikey> mkset;

mkset.insert(Tmultikey(1,5));
mkset.insert(Tmultikey(6,4));
mkset.insert(Tmultikey(3,7));
mkset.insert(Tmultikey(1,6));

Tmultikey::erase(mkset,Tmultikey::Tsecondary(4));
Tmultikey::erase(mkset,Tmultikey::Tprimary(1));

// If you have compose_f_gx_hx and siblings (non-standard functions)
// Removes keys where primary is 1 or secondary is 4
Tmultikey::erase(mkset, compose_f_gx_hx(
std::logical_or<bool>(),
Tmultikey::Tprimary(1),
Tmultikey::Tsecondary(4)));

return 0;
}

TIT

I have not really followed the compose_f_gx_hx, but I can see one
problem immediatly, when an item is erased from set the iterator
becomes invalid and cannot be incremented.
c.erase(pos++);

Oct 28 '05 #6
Ninan wrote:

I have not really followed the compose_f_gx_hx


compose_f_gx_hx comes from Josuttis. He gives examples of some
composition adapters in his library book. Very useful.

compose_f_gx_hx is f(g(x),h(x))
Oct 28 '05 #7
TIT
Ninan sade:
TIT wrote:

<snip>
// Eraser for std::set
template<typename Compare>
static void erase(std::set<Tmultikey> & c, Compare op) {
typename std::set<Tmultikey>::iterator pos = c.begin();
while(pos != c.end()) {
if(op(&(*pos))) {
c.erase(pos++);
} else ++pos;
}
} <snip>
TIT


I have not really followed the compose_f_gx_hx, but I can see one
problem immediatly, when an item is erased from set the iterator
becomes invalid and cannot be incremented.
c.erase(pos++);


There is no problem there.

TIT
Oct 28 '05 #8
TIT
TIT sade:
Ninan sade:
TIT wrote:


<snip>
// Eraser for std::set
template<typename Compare>
static void erase(std::set<Tmultikey> & c, Compare op) {
typename std::set<Tmultikey>::iterator pos = c.begin();
while(pos != c.end()) {
if(op(&(*pos))) {
c.erase(pos++);
} else ++pos;
}
}
<snip>

TIT

I have not really followed the compose_f_gx_hx, but I can see one
problem immediatly, when an item is erased from set the iterator
becomes invalid and cannot be incremented. c.erase(pos++);


There is no problem there.

TIT


And in case you don't believe my simple answer let me quote the
actual standard:

23.1.2/8

"[...], and the erase members shall invalidate only iterators
and references to the erased elements"

TIT
Oct 28 '05 #9
TIT
TIT sade:
Ninan sade:
TIT wrote:


<snip>
// Eraser for std::set
template<typename Compare>
static void erase(std::set<Tmultikey> & c, Compare op) {
typename std::set<Tmultikey>::iterator pos = c.begin();
while(pos != c.end()) {
if(op(&(*pos))) {
c.erase(pos++);
} else ++pos;
}
}
<snip>

TIT

I have not really followed the compose_f_gx_hx, but I can see one
problem immediatly, when an item is erased from set the iterator
becomes invalid and cannot be incremented. c.erase(pos++);


There is no problem there.

TIT


And you might want to read about the difference
between postfix and prefix operator++.

TIT
Oct 28 '05 #10

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

17
6824
by: Paul MG | last post by:
Hi Template partial specialization always seems like a fairly straightforward concept - until I try to do it :). I am trying to implement the input sequence type (from Stroustrup section...
4
2270
by: Erik Wikström | last post by:
In school (no I will not ask you to do my schoolwork for me) we talked about policy-based design and got an assignment where we got the a code- fragment from a stack-implementation. The idea with...
2
7901
by: Christian Staffe | last post by:
Hi, I would like to check for a partial match between an input string and a regular expression using the Regex class in .NET. By partial match, I mean that the input string could not yet be...
1
3459
by: Liu, Mingyi | last post by:
Sorry if this question has been asked before. I tried to search in postgres mailing lists at http://archives.postgresql.org/pgsql-general/ just now and it gave me error "An error occured! Can not...
4
6576
by: wecka | last post by:
Hello All, Does any one know how to use the form filter in Access to provide partial match? When you choose to "form filter," all text boxes will convert to combo boxes where you can choose from...
5
5681
by: SQL Learner | last post by:
Hi Alex (Kuznetsov) and All, This is to follow up with my last post, "Link two tables using partial word match". How can I UPDATE table using partial word match? How can I write a SQL statement...
3
2873
by: chungiemo | last post by:
Hi I have a project with access it has 2 non-related tables in access, which should have been related by ID, due to the poor data entry standards I am trying to match records from table 1 to...
1
2932
by: chungiemo | last post by:
Hi thought I would do another thread as this one is a bit different from the previous problem I am looking for a solution to the relating problem Comparing 2 access databases with 2 tables,...
1
2072
by: tbucha3 | last post by:
I have two tables that I have to get information from to produce another table. Both tables come from separate resources, one has partial accounts with addresses and the other has complete account...
16
5168
by: vorlonfear | last post by:
I have been working on this for a while now and I wanted to see if someone could assist me. I have 2 tables each with 5 fields. 4 of the fields are 2 character strings, then the final field is the...
0
7225
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However,...
0
7326
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers,...
1
7046
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows...
0
5629
agi2029
by: agi2029 | last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing,...
1
5053
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 1 May 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome a new...
0
4707
by: conductexam | last post by:
I have .net C# application in which I am extracting data from word file and save it in database particularly. To store word all data as it is I am converting the whole word file firstly in HTML and...
0
3182
by: adsilva | last post by:
A Windows Forms form does not have the event Unload, like VB6. What one acts like?
0
1558
by: 6302768590 | last post by:
Hai team i want code for transfer the data from one system to another through IP address by using C# our system has to for every 5mins then we have to update the data what the data is updated ...
1
766
muto222
by: muto222 | last post by:
How can i add a mobile payment intergratation into php mysql website.

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.