LinuxQuestions.org

LinuxQuestions.org (/questions/)
-   Programming (https://www.linuxquestions.org/questions/programming-9/)
-   -   C++ STL key/value pairs strangely refuse to be eased!! (https://www.linuxquestions.org/questions/programming-9/c-stl-key-value-pairs-strangely-refuse-to-be-eased-194899/)

nyk 06-18-2004 04:11 AM

C++ STL key/value pairs strangely refuse to be eased!!
 
I write a (bio-tool) program that creates STL key/value pairs like these for example:
"AGA"= 3
"URG" = 5
"ABCD" = 1
"TRD" = 1

Now I am only interested in the pairs with values above 2, so I wrote the following code to remove the ones below:

typedef map<string,int> StringIntMap;
StringIntMap ph;
StringIntMap::iterator pos;

for (pos=ph.begin();pos!=ph.end();++pos) {
if (pos->second<3) {ph.erase(pos);}
}

The majority (thousends) of pairs with values below 3 get deleted, but still some pairs with values of 1 remain!! I do not understand, because the code above should logically delete them all! Does anybody have an idea why the could escape deletion?

dakensta 06-18-2004 05:33 AM

erase() on a map will not invalidate iterators EXCEPT the one that points the item being erased, so you need to separate the 'iterating' iterator from the 'erasing' iterator.

Code:

for (map_type::iterator iter=the_map.begin(); iter!=the_map.end(); )
{
  if (iter->second < 3)
    the_map.erase(iter++);  // post increment and erase
  else
    ++iter;  // or iter++
}

This should work because iter++ increments the actual iterator and returns a temporary that points to the old position (the one you want to erase), thus invalidating only the temporary iterator.

p.s. pop your code samples between code tags like this
[ code ]
YOUR CODE
[ /code ]

with no spaces in the brackets - it makes it easier to read :D

nyk 06-18-2004 08:15 AM

thanks, but it didn't help..

whats the difference between x++ and ++x again?

another strange thing is that the way I am outputing the data should never even show the key/value pairs with values lower that 5, according to this code:

Code:

typedef map<string,int> StringIntMap;
StringIntMap phc;

for (k=maxi;k>4;k--) {hash_sort(k);}

void hash_sort(int n) {
        StringIntMap::iterator pos;
        for (pos=phc.begin();pos!=phc.end();++pos) {
                if (pos->second==n) {
                        pos->second/=pos->first.size();
                        cout <<pos->second<<"x "<<pos->first<<endl;
                }
        }
}

But still I get this output (for example):

Value / Key
==========
3x AL
3x CR
3x GA
3x GC
3x GF
3x LL
3x LR
3x PH
3x PV
3x RE
3x RV
3x TG
3x VL
3x VP
2x LA
2x RL
1x RRR

dakensta 06-18-2004 09:08 AM

Code:

// ++x does something like this:
const type& operator++()
{
 this +=1;
 return *this;
}

//x++ does something like this:
const type operator++ (int i)
{
  type temp=*this;
  *this += 1;
  return temp;
}

So if you have a statement involving '++' it determines whether you pre-increment and use the increased value or post-increment - add one and use the old value.
y = ++x; and y = x++; are different.

but I am not sure exactly what is 'officially' mandated wrt implementation.

I am slightly surprised this is not working - I would generally look at my own code before searching for an error elsewhere - but this technique is often suggested on places like comp.lang.c++ where contributors tend to be somewhat pedantic to say the least!

I am not clear what the purpose of this line is (wrt output):
Code:

pos->second/=pos->first.size();
You are changing the value by dividing by the length of the key.

Here : 1x RRR
key: RRR had a value: 5, no?
similarly, LA and RL had values of 5 and the rest had values of 6 or 7.

... or have I missed something?

nyk 06-18-2004 09:30 AM

yes, you're right about that.
AFTER I want to delete the key with value smaller than 3, I multiply the value by the length of the key, and revert this by dividing before the output.
I do this, because I want to sort the key/value pairs that way. So when I filter out the value=1 pairs after the dividing, I don't get them outputted, as expected. Sorry, this was my mistake!
But the key/value pairs with value=1 STILL EXIST, even though I deleted them with your method. I mean because the multiplication is afterwards. This is the whole code I am talking about:

Code:

int main(int argc, char *argv[]) {
        long i,k,j,pl,l,sc;string prot,ss;
        if (argc<2) {printf(HELP);exit(-1);}
        if (load_fasta(argv[1],-1)==-1) {exit(1);}
        for (i=0;i<numseq;i++) {
                printf("%s\n",desc[i]);maxi=0;
                prot=seq[i];pl=strlen(seq[i]);
                ph.erase(ph.begin(),ph.end());
                phc.erase(ph.begin(),ph.end());
                for (k=int(pl/2);k>1;k--) {
                        for (j=0;j<pl-k+1;j++) {
                                ss=prot.substr(j,k);ph[ss]++;
                        }
                }
                hash_clean();
                for (k=maxi;k>4;k--) {hash_sort(k);}
        }
}

void hash_sort(int n) {
        for (q=phc.begin();q!=phc.end();++q) {
                if (q->second==n) {
                        q->second/=q->first.size();
                        if (q->second>1) {
                                cout <<q->second<<"x "<<q->first<<endl;
                        }
                }
        }
}

void hash_clean(void) {
        for (q=ph.begin();q!=ph.end();) {
                if (q->second<2) {ph.erase(q++);} else {q++;}
        }
        for (q=ph.begin();q!=ph.end();++q) {
                if (!inhash(q->first)) {
                        phc[q->first]=q->second*q->first.size();
                        if (phc[q->first]>maxi) {maxi=phc[q->first];}
                }
        }
}

bool inhash(string k) {
        StringIntMap::iterator p;
        bool r=false;string ik;
        for (p=ph.begin();p!=ph.end();++p) {
                ik=p->first;
                if ((ik.find(k,0)!=string::npos) && (ik!=k)) {r=true;}
        }
        return r;
}


dakensta 06-18-2004 12:53 PM

I tried to compile your code, using globals:
Code:

typedef map<string,int> StringIntMap;

StringIntMap ph, phc;
StringIntMap::iterator q;
int maxi=0;

and using a random string of 1000 characters (from a selection of 20 - I guessed) but I haven't found any instances of 1xABCD but then again I don't have the same data - I don't know if you can post the shortest sequence that gives this error?

Why not put a check in hash_clean after the first loop if you think the error is there?
Code:

for (StringIntMap::iterator iter=ph.begin(); iter!=ph.end(); ++iter)
  if (iter->second < 2) cout << "Error\n";



All times are GMT -5. The time now is 01:24 PM.