locked
how to remove elements of one vector from another vector RRS feed

  • Question

  • hi,all, I have two vectors A and B, B is a subset of A, now i want to remove elements of B from A, how to do that?

    cheers

    daiyue 

    Sunday, July 10, 2011 1:28 PM

Answers

  • One possible one for your case would be:

    struct ExistsInVector
    {
    	ExistsInVector(const std::vector<int>& vec) : m_vec(vec) {
    	}
    	bool operator() (int i) {
    		return (std::find(m_vec.begin(), m_vec.end(), i) != m_vec.end());
    	}
    private:
    	const std::vector<int>& m_vec;
    };
    

    which would be used with the std::remove_if function like this:

    std::remove_if(A.begin(), A.end(), ExistsInVector(B));
    

    To completely achieve your goal, however, you would need to erase the trailing elements left behind in "A". ending up using the Erase-remove idiom, like this:

    A.erase( std::remove_if(A.begin(), A.end(), ExistsInVector(B)), A.end() );
    

    - Shoaib.

    • Proposed as answer by ildjarn Sunday, July 10, 2011 10:06 PM
    • Marked as answer by daiyueweng Sunday, July 10, 2011 10:20 PM
    Sunday, July 10, 2011 9:55 PM
  • >I have two vectors A and B, B is a subset of A, now i
    >want to remove elements of B from A, how to do that?

    >how to code the predicate function in this case.

    The code will depend on what type of objects are
    in the vectors. You may not need a predicate:

    #include "stdafx.h"
    #include <vector>
    #include <iostream>
    #include <algorithm>
    using namespace std;

    int _tmain(int argc, _TCHAR* argv[])
    {
      vector<int> vint, vints;
      for(int i=0; i<20; ++i)
        {
        vint.push_back(i);
        if(!(i % 2)) vints.push_back(i);
        }
      cout << "vector 1 before deletes:\n";
      vector<int>::size_type n;
      for(n=0; n<vint.size(); ++n)
        {
        cout << vint[n] << ' ';
        }
      cout << "\nvector 2:\n";
      for(n=0; n<vints.size(); ++n)
        {
        cout << vints[n] << ' ';
        }
      vector<int>::iterator vIter;
      for(vIter = vints.begin(); vIter < vints.end(); ++vIter)
        {
        vint.erase(find(vint.begin(), vint.end(), *vIter));
        }   
      cout << "\nvector 1 after deletes:\n";
      for(n=0; n<vint.size(); ++n)
        {
        cout << vint[n] << ' ';
        }

      return 0;
    }

    E&OE

    - Wayne
    • Marked as answer by daiyueweng Sunday, July 10, 2011 10:20 PM
    Sunday, July 10, 2011 10:13 PM
  • i think the trailing elements left behind in A is fine?why should i remove them?

    Because you said you "want to remove elements of B from A". Give it a try yourself - you will understand why you need to remove them.

    As an example, suppose A = (1,2,3,4,5,6,7,8,9) and B = (1,3,5,7,9). Without using A.erase(), you will end up (2,4,6,8,5,6,7,8,9) which I don't think is what you want. To end up with (2,4,6,8), you would need to erase those trailing elements.

    You should read the Erase-remove idiom page and search the Internet more for this phrase for a better understanding of that.

    - Shoaib.

    • Marked as answer by daiyueweng Sunday, July 10, 2011 10:20 PM
    Sunday, July 10, 2011 10:14 PM

All replies

  • You can use the remove_if function from <algorithm> and a predicate function or lambda. If you keep you vectors sorted or use sets, then consider set_difference.

    • Marked as answer by daiyueweng Sunday, July 10, 2011 8:02 PM
    • Unmarked as answer by daiyueweng Sunday, July 10, 2011 8:55 PM
    Sunday, July 10, 2011 4:17 PM
  • could you make an example of using remove_if in my case?

    especially, how to code the predicate function in this case.


    Sunday, July 10, 2011 8:47 PM
  • One possible one for your case would be:

    struct ExistsInVector
    {
    	ExistsInVector(const std::vector<int>& vec) : m_vec(vec) {
    	}
    	bool operator() (int i) {
    		return (std::find(m_vec.begin(), m_vec.end(), i) != m_vec.end());
    	}
    private:
    	const std::vector<int>& m_vec;
    };
    

    which would be used with the std::remove_if function like this:

    std::remove_if(A.begin(), A.end(), ExistsInVector(B));
    

    To completely achieve your goal, however, you would need to erase the trailing elements left behind in "A". ending up using the Erase-remove idiom, like this:

    A.erase( std::remove_if(A.begin(), A.end(), ExistsInVector(B)), A.end() );
    

    - Shoaib.

    • Proposed as answer by ildjarn Sunday, July 10, 2011 10:06 PM
    • Marked as answer by daiyueweng Sunday, July 10, 2011 10:20 PM
    Sunday, July 10, 2011 9:55 PM
  • i think the trailing elements left behind in A is fine?why should i remove them?

     

    Sunday, July 10, 2011 10:03 PM
  • >I have two vectors A and B, B is a subset of A, now i
    >want to remove elements of B from A, how to do that?

    >how to code the predicate function in this case.

    The code will depend on what type of objects are
    in the vectors. You may not need a predicate:

    #include "stdafx.h"
    #include <vector>
    #include <iostream>
    #include <algorithm>
    using namespace std;

    int _tmain(int argc, _TCHAR* argv[])
    {
      vector<int> vint, vints;
      for(int i=0; i<20; ++i)
        {
        vint.push_back(i);
        if(!(i % 2)) vints.push_back(i);
        }
      cout << "vector 1 before deletes:\n";
      vector<int>::size_type n;
      for(n=0; n<vint.size(); ++n)
        {
        cout << vint[n] << ' ';
        }
      cout << "\nvector 2:\n";
      for(n=0; n<vints.size(); ++n)
        {
        cout << vints[n] << ' ';
        }
      vector<int>::iterator vIter;
      for(vIter = vints.begin(); vIter < vints.end(); ++vIter)
        {
        vint.erase(find(vint.begin(), vint.end(), *vIter));
        }   
      cout << "\nvector 1 after deletes:\n";
      for(n=0; n<vint.size(); ++n)
        {
        cout << vint[n] << ' ';
        }

      return 0;
    }

    E&OE

    - Wayne
    • Marked as answer by daiyueweng Sunday, July 10, 2011 10:20 PM
    Sunday, July 10, 2011 10:13 PM
  • i think the trailing elements left behind in A is fine?why should i remove them?

    Because you said you "want to remove elements of B from A". Give it a try yourself - you will understand why you need to remove them.

    As an example, suppose A = (1,2,3,4,5,6,7,8,9) and B = (1,3,5,7,9). Without using A.erase(), you will end up (2,4,6,8,5,6,7,8,9) which I don't think is what you want. To end up with (2,4,6,8), you would need to erase those trailing elements.

    You should read the Erase-remove idiom page and search the Internet more for this phrase for a better understanding of that.

    - Shoaib.

    • Marked as answer by daiyueweng Sunday, July 10, 2011 10:20 PM
    Sunday, July 10, 2011 10:14 PM