2016-09-07 4 views
2

ベクトルAとベクトルBに表示される要素を削除する必要がありますが、ベクトルAにのみ含まれる要素は削除する必要があります。必ずしも互いに等しいとは限らない。場合C++:1つのベクトル内にある要素を別のベクトルから削除する

たとえば、: ベクトルAに値が含ま< 1,4,66,22> ベクトルBは値が含ま< 1,22,44,93,102,543>

次に動作を予備成形した後: < 44,93,102,543>

が含まれている必要があり、ベクトルAは< 4,66> ベクトルBが含まれている必要があり、私は、forループの両方をループする必要があると値をstrncmpはまたは私は合理化するために使用できる機能ですかプロセス? これは私が試みたものですが、うまくいかないようです。

string rawInput; 
string fileInput; 
vector<string> stdInput; //vector to hold standard input values 
vector<string> fileList; //vector to hold file values 

sizeIn = stdInput.size(); 
sizeFile = fileList.size(); 

if (sizeIn >= sizeFile) 
    { 
     for (count = 0;count <= sizeIn; count++) 
     { 
      for (count1 = 0; count1 <= sizeFile; count1++) 
      { 
       if (stdInput[count1] == fileList[count]) 
       { 
        stdInput.erase(stdInput.begin()+count1-1); 
        fileList.erase(fileList.begin()+count-1); 

       } 

      } 
     } 
    } 
    else 
    { 
     for (count = 0; count <= sizeFile; count ++) 
     { 
      for (count1 = 0; count1 <= sizeIn; count1++) 
      { 
       if (stdInput[count] == fileList[count1]) 
       { 
        stdInput.erase(stdInput.begin()+count-1); 
        fileList.erase(fileList.begin()+count1-1); 

       } 
      } 
     } 
    } 
+0

それが保持要素の相対的な順序を維持するために必要ですか? – Arun

+5

両方のベクトルがソートされている場合は、['std :: set_difference'](http://en.cppreference.com/w/cpp/algorithm/set_difference)を使うことができます。 –

+0

いいえ、私はそれらをsort(fileList.begin()、fileList.end())を介して使用します。 after – hournet562

答えて

0

次のようなものを試すことがあります。

// Create sets from vectors. This eliminates the duplicate elements. 
const unordered_set<int> setA{vecA.cbegin(), vecA.cend()}; 
const unordered_set<int> setB{vecB.cbegin(), vecB.cend()}; 

PopulateSetDiff(vecA, setA, setB); 
PopulateSetDiff(vecB, setB, setA); 

// Populate 'vec' with 'set1 - set2' 
template <typename T> 
void PopulateSetDiff(
    vector<T>& vec, 
    unordered_set<T> const& set1, 
    unordered_set<T> const& set2) { 
    vec.clear(); 
    for (const auto elem : set1) { 
    if (set2.find(elem) == set2.cend()) { 
     vec.push_back(elem); 
    } 
    } 
    vec.shrink_to_fit(); 
} 
1

これは多くの作業です。私はstd::set_differenceを示唆しているだろうが、あなたの場所でそれをやりたいので、このコードは良いアルゴリズムの複雑さにあなたのためにそれを行います。

template<typename T> 
void remove_intersection(std::vector<T>& a, std::vector<T>& b){ 
    std::unordered_multiset<T> st; 
    st.insert(a.begin(), a.end()); 
    st.insert(b.begin(), b.end()); 
    auto predicate = [&st](const T& k){ return st.count(k) > 1; }; 
    a.erase(std::remove_if(a.begin(), a.end(), predicate), a.end()); 
    b.erase(std::remove_if(b.begin(), b.end(), predicate), b.end()); 
} 

はC++綺麗ではないですか? :-)


Aデモ:

int main(){ 
    std::vector<int> a = {1,4,66,22}; 
    std::vector<int> b = {1,22,44,93,102,543}; 

    remove_intersection(a, b); 

    for(auto k : a) std::cout << k << ' '; 
    std::cout << std::endl; 
    for(auto k : b) std::cout << k << ' '; 
} 

出力:

4 66 
44 93 102 543 

上記の方法の多くのバリエーションがありますLive On Coliru

それを参照してください。たとえば、countが実際にその数が多い場合に時間がかかることがあると心配している場合は、最大2つの要素を見つけてカウントする単純な関数を実装できます。別のもの:あなたは単に2つの異なる順序のないセットを使うことができます。

0

いいえ、私はソート(fileList.begin()、fileList.end())でそれらを使用します。後で

だから漸近的にそれは前にソートするのと同じです。

set_differenceを使用して、あなたのような何かを行うことができます:

template<typename T> 
void remove_intersection(std::vector<T>* c1, std::vector<T>* c2) { 
    assert(c1 != nullptr); 
    assert(c2 != nullptr); 

    std::sort(std::begin(*c1), std::end(*c1)); // O(n1 logn1) 
    std::sort(std::begin(*c2), std::end(*c2)); // O(n2 logn2) 

    std::vector<T> difference1, difference2; 
    difference1.reserve(c1->size()); 
    difference2.reserve(c2->size()); 

    std::set_difference(std::begin(*c1), std::end(*c1), 
         std::begin(*c2), std::end(*c2), 
         std::back_inserter(difference1)); 
    // O(2*[N1 + N2 - 1]) 

    std::set_difference(std::begin(*c2), std::end(*c2), 
         std::begin(*c1), std::end(*c1), 
         std::back_inserter(difference2)); 
    // O(2*[N1 + N2 - 1]) 

    *c1 = std::move(difference1); // O(1) 
    *c2 = std::move(difference2); // O(1) 
} 
関連する問題