Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C++ - Appending one Vector to another, with removal of duplicates?

Tags:

c++

vector

I'd like to append one vector (vectorAlpha) to the end of another vector (vectorBeta). There's two different approaches I could think of, and I'd like to know how to do each one.

The first approach was to append the second vector and remove all duplicate items from the new vector. The other approach is to leave duplicates in the individual vectors alone, but not adding any items from vectorBeta if they are already present in vectorALpha.

For instance if the vectors are vector with the following values:

vectorAlpha:

First line of alpha
An alpha line
An alpha line
Some line
Alpha fifth line

vectorBeta:

Beta first line
A beta line
A beta line
Some line
Beta fifth line

I think the first approach would result in the combined vector:

First line of alpha
An alpha line
Some line
Alpha fifth line
Beta first line
A beta line
Beta fifth line

While the second approach would just be both arrays combined, but with the 'Some line' from the second vector not added:

First line of alpha
An alpha line
An alpha line
Some line
Alpha fifth line
Beta first line
A beta line
A beta line
Beta fifth line

What would be the C++ code to use for these two appraoches?

like image 232
Tristan Avatar asked Apr 03 '11 10:04

Tristan


2 Answers

Since it became clear that

  1. you only wanted duplicates remove entries from vecB if they existed in vecA, not duplicates in general
  2. you wanted to preserve the ordering

The answer should (obviously?) be std::remove_copy_if. Call it thusly:

#include <vector>
#include <algorithm>

typedef std::vector<int> Vec;
struct Contained
{
    const Vec& _sequence;
    Contained(const Vec &vec) : _sequence(vec) {}
    bool operator()(int i) const 
    { 
        return _sequence.end() != std::find(_sequence.begin(), _sequence.end(), i);
    }
};

int main()
{
    Vec vecA;
    Vec vecB;

    std::remove_copy_if(vecB.begin(), vecB.end(), back_inserter(vecA), Contained(vecA));
}

You might want to optimize the predicate depending on the size and nature of vecA:

#include <set>

template <typename T>
struct Contained
{
    const std::set<T> _set;
    template <typename It> Contained(const It& begin, const It& end) : _set(begin, end) {}
    bool operator()(const T& i) const 
    { 
        return _set.end() != _set.find(i);
    }
};

Which would be used as Contained<int>(vecA.begin(), vecA.end()). The full code is compiling on codepad.org

Cheers

like image 168
sehe Avatar answered Nov 14 '22 03:11

sehe


Is the order of the elements in the two vectors important? If not, then you should probably be using sets instead.

like image 30
swestrup Avatar answered Nov 14 '22 02:11

swestrup