Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > comp.lang.c++ > #7219 > unrolled thread

STL set Problem

Started bymrc2323@cox.net (Mike Copeland)
First post2011-06-28 15:38 -0700
Last post2011-07-06 21:29 +0200
Articles 7 — 4 participants

Back to article view | Back to comp.lang.c++


Contents

  STL set Problem mrc2323@cox.net (Mike Copeland) - 2011-06-28 15:38 -0700
    Re: STL set Problem Ian Collins <ian-news@hotmail.com> - 2011-06-29 10:57 +1200
      Re: STL set Problem mrc2323@cox.net (Mike Copeland) - 2011-06-28 16:04 -0700
    Re: STL set Problem Kai-Uwe Bux <jkherciueh@gmx.net> - 2011-06-29 01:00 +0200
      Re: STL set Problem mrc2323@cox.net (Mike Copeland) - 2011-06-28 16:07 -0700
      Re: STL set Problem mrc2323@cox.net (Mike Copeland) - 2011-06-28 21:10 -0700
    Re: STL set Problem Werner Erasmus <werasm@gmail.com> - 2011-07-06 21:29 +0200

#7219 — STL set Problem

Frommrc2323@cox.net (Mike Copeland)
Date2011-06-28 15:38 -0700
SubjectSTL set Problem
Message-ID<MPG.287405c21e5896de9896bc@news.eternal-september.org>
   I have the following application stub that compiles and works.  Now I 
wish to add "find" functionality (based on matching the "baseBib" 
element), and I can't see from the documentation or examples I've found 
hoe to do so.  The STL set "find" seems meant only for scalar objects 
(but the optional insert parameter supports field-based ordering...).
   What am I missing in this?  TIA

#pragma warning (disable:4786)
#include <set>
#include <iostream>
#include <string>
using namespace std;

class Entrant
{
public:
	int  baseBib;
	char baseEvent;
};
class LoToHigh
{
public:
	bool operator()(Entrant s1, Entrant s2)
	{
	    if(s1.baseBib < s2.baseBib) return true;
	    else                        return false;
	}
};

int main(int argc, char* argv[])
{
	set <Entrant, LoToHigh> myEntrant;
	set <Entrant, LoToHigh>::iterator it;
	Entrant a1, a2, a3;

	a1.baseBib = 2077, a1.baseEvent = 'a';
	a2.baseBib = 2066, a2.baseEvent = 'b';
	a3.baseBib = 2055, a3.baseEvent = 'a';
	myEntrant.insert(a1), myEntrant.insert(a2);
	myEntrant.insert(a1), myEntrant.insert(a3);
	cout << "The # of Entrants is " << myEntrant.size() << endl;
	for(it = myEntrant.begin(); it != myEntrant.end(); it++)
	{
	    cout << it->baseBib << "\t" << it->baseEvent << endl;
	}
	return 0;
}

[toc] | [next] | [standalone]


#7220

FromIan Collins <ian-news@hotmail.com>
Date2011-06-29 10:57 +1200
Message-ID<96v4jlFfpqU3@mid.individual.net>
In reply to#7219
On 06/29/11 10:38 AM, Mike Copeland wrote:
>     I have the following application stub that compiles and works.  Now I
> wish to add "find" functionality (based on matching the "baseBib"
> element), and I can't see from the documentation or examples I've found
> hoe to do so.  The STL set "find" seems meant only for scalar objects
> (but the optional insert parameter supports field-based ordering...).
>     What am I missing in this?  TIA

Have you considered using a map rather than a set?

-- 
Ian Collins

[toc] | [prev] | [next] | [standalone]


#7222

Frommrc2323@cox.net (Mike Copeland)
Date2011-06-28 16:04 -0700
Message-ID<MPG.28740bf747e740c49896bd@news.eternal-september.org>
In reply to#7220
> >     I have the following application stub that compiles and works.  Now I
> > wish to add "find" functionality (based on matching the "baseBib"
> > element), and I can't see from the documentation or examples I've found
> > hoe to do so.  The STL set "find" seems meant only for scalar objects
> > (but the optional insert parameter supports field-based ordering...).
> >     What am I missing in this?  TIA
> 
> Have you considered using a map rather than a set?
 
   Briefly.  Using a map seems a bit more complex in coding and 
processing (I can't verify the latter), so I though I'd try a set for 
this simple application need.  (I don't know if it's faster or less 
resource-intensive, and this is an investigational experiment.)

[toc] | [prev] | [next] | [standalone]


#7221

FromKai-Uwe Bux <jkherciueh@gmx.net>
Date2011-06-29 01:00 +0200
Message-ID<iudmdk$aek$1@hoshi.visyn.net>
In reply to#7219
Mike Copeland wrote:

>    I have the following application stub that compiles and works.  Now I
> wish to add "find" functionality (based on matching the "baseBib"
> element), and I can't see from the documentation or examples I've found
> hoe to do so.  The STL set "find" seems meant only for scalar objects
> (but the optional insert parameter supports field-based ordering...).
>    What am I missing in this?

I don't understand the bit about scalar objects.


> #pragma warning (disable:4786)
> #include <set>
> #include <iostream>
> #include <string>
> using namespace std;
> 
> class Entrant
> {
> public:
> int  baseBib;
> char baseEvent;
> };
> class LoToHigh
> {
> public:
> bool operator()(Entrant s1, Entrant s2)
> {
> if(s1.baseBib < s2.baseBib) return true;
> else                        return false;
> }
> };

The function std::set<>::find() uses the notion of equivalence. Two entries 
a and b are equivalent when neither a<b nor b<a. In your case, that should 
amount to the baseBib fields being equal. Thus, if you are given an int 
value bib, you can search for that, by doing:

  find( Entrant( bib, 0 ) )

I.e., you turn this into a meaningless Entrant object with correct baseBib 
value and search for that. The invented value for baseEvent will be ignored 
within the comparison predicate.


> int main(int argc, char* argv[])
> {
> set <Entrant, LoToHigh> myEntrant;
> set <Entrant, LoToHigh>::iterator it;
> Entrant a1, a2, a3;
> 
> a1.baseBib = 2077, a1.baseEvent = 'a';
> a2.baseBib = 2066, a2.baseEvent = 'b';
> a3.baseBib = 2055, a3.baseEvent = 'a';
> myEntrant.insert(a1), myEntrant.insert(a2);
> myEntrant.insert(a1), myEntrant.insert(a3);
> cout << "The # of Entrants is " << myEntrant.size() << endl;
> for(it = myEntrant.begin(); it != myEntrant.end(); it++)
> {
> cout << it->baseBib << "\t" << it->baseEvent << endl;
> }
> return 0;
> }

Things to ponder:

a) Would std::map<> be better for this.
b) Are baseBib values guaranteed to be unique? std::set<> will purge 
previous entries when equivalent entries arive.


Best,

Kai-Uwe Bux

[toc] | [prev] | [next] | [standalone]


#7223

Frommrc2323@cox.net (Mike Copeland)
Date2011-06-28 16:07 -0700
Message-ID<MPG.28740c8bf734cbc9896be@news.eternal-september.org>
In reply to#7221
> >    I have the following application stub that compiles and works.  Now I
> > wish to add "find" functionality (based on matching the "baseBib"
> > element), and I can't see from the documentation or examples I've found
> > hoe to do so.  The STL set "find" seems meant only for scalar objects
> > (but the optional insert parameter supports field-based ordering...).
> >    What am I missing in this?
> 
> I don't understand the bit about scalar objects.

   By that I mean, "a set of int" or "a set of char".  My application 
needs a structure.  (Perhaps my usage of "scalar" isn't appropriate...)  
8<{{

[toc] | [prev] | [next] | [standalone]


#7224

Frommrc2323@cox.net (Mike Copeland)
Date2011-06-28 21:10 -0700
Message-ID<MPG.287453b6f12050629896bf@news.eternal-september.org>
In reply to#7221
> > #include <set>
> > #include <iostream>
> > #include <string>
> > using namespace std;
> > 
> > class Entrant
> > {
> > public:
> > int  baseBib;
> > char baseEvent;
> > };
   <sigh>  I've decided that doing this as a set is to difficult and 
convoluted.  I changed it to a map, and it's working.  Perhaps a lesson 
learned... 8<{{

[toc] | [prev] | [next] | [standalone]


#7546

FromWerner Erasmus <werasm@gmail.com>
Date2011-07-06 21:29 +0200
Message-ID<VqCdnY0U9IQDKonTnZ2dnUVZ8rWdnZ2d@saix.net>
In reply to#7219
Mike Copeland wrote:
>     I have the following application stub that compiles and works.  Now I
> wish to add "find" functionality (based on matching the "baseBib"
> element), and I can't see from the documentation or examples I've found
> hoe to do so.  The STL set "find" seems meant only for scalar objects
> (but the optional insert parameter supports field-based ordering...).

I have some modified code below. Typically (IMHO) for set items
it is good to overload "operator <" and use std algorithms (like
greater or less (default) ) to perform sorting (as these are
implemented in terms of less).

#include <set>
#include <iostream>
#include <string>
#include <algorithm>
using namespace std;

class Entrant
{
public:
   Entrant( int bBib, char bEvt = 0 )
   : baseBib( bBib ), baseEvent( bEvt )
   {
   }
   int  baseBib;
   char baseEvent;

   bool operator < ( const Entrant& other ) const
   { return baseBib < other.baseBib; }
};

ostream& operator << ( ostream& os, const Entrant& entrant )
{
   return( os << "Entrant( " << entrant.baseBib << ", "
     << entrant.baseEvent << " )" );
}

int main(int argc, char* argv[])
{
	typedef set<Entrant> LowToHighEntrantSet; //Uses less
	typedef set<Entrant, std::greater<Entrant> > HighToLowEntrantSet;

         LowToHighEntrantSet myEntrant;
	Entrant a1( 2077, 'a' ), a2( 2066, 'b' ), a3( 2055, 'c' );

	myEntrant.insert(a1), myEntrant.insert(a2);
	myEntrant.insert(a1), myEntrant.insert(a3);
         // Note: Inserting a1 twice (above) has no value...

         cout << "The # of Entrants is " << myEntrant.size() << endl;
	LowToHighEntrantSet::iterator it;
	for(it = myEntrant.begin(); it != myEntrant.end(); it++)
	{
	    cout << it->baseBib << "\t" << it->baseEvent << endl;
	}


         // ....Finding....
         it = myEntrant.find( Entrant( 2077 ) );
         if( it != myEntrant.end() )
         {
           cout << "Found entrant: " << *it << endl;
         }
	return 0;
}

Kind regards,

Werner

[toc] | [prev] | [standalone]


Back to top | Article view | comp.lang.c++


csiph-web