簡體   English   中英

相當於Java ArrayList方法removeAll的C ++

[英]C++ equivalent to Java ArrayList method removeAll

Java ArrayList removeAll()方法將一個集合作為參數,並從調用該方法的ArrayList中刪除此集合。 如何在c ++中的vector上完成等效動作?

std::vector沒有這樣的方法。

標准庫的設計理念是我們不實現類中的所有內容。 取而代之的是,有很多對容器進行操作的算法。

http://en.cppreference.com/w/cpp/algorithm

不幸的是,標准算法之間也沒有等效的方法。 但是您可以基於它們編寫一個算法。

#include <algorithm>

template <class Container, class RemoveTargetContainer>
typename Container::iterator remove_for(Container& container, const RemoveTargetContainer& targets)
{
    auto container_first = std::begin(container);
    auto container_last = std::end(container);

    std::for_each(std::begin(targets), std::end(targets),
        [&](typename RemoveTargetContainer::const_reference target)
        {
            container_last = std::remove(container_first, container_last, target);
        }
    );

    return container_last;
}

這是用法:

#include <iostream>
#include <vector>
#include <deque>

int main()
{
    std::vector<int> myContainer { 1,2,3,4,5,6,7,8 };
    std::deque<int> removalTargets { 1,3,5,7 };

    myContainer.erase(remove_for(myContainer, removalTargets), std::end(myContainer));

    for (const auto& x : myContainer)
        std::cout << x << " ";
    std::cout << std::endl;
}

PS:我不喜歡名字removeAll 這是誤導。

這是一個通用的解決方案:

#include <set>
#include <vector>
#include <algorithm>

// Remove all in c2 from c1
template<typename Collection1, typename Collection2>
void removeAll(Collection1& c1, const Collection2& c2)
{
    for(auto&& i: c2)
        c1.erase(std::remove_if(c1.begin(), c1.end(), [i](decltype(i) i1){return i == i1;}), c1.end());
}

int main()
{
    std::vector<int> v1 {1, 5, 3, 6, 4, 6, 2, 6, 7};
    std::set<int> v2 {5, 6, 2};

    removeAll(v1, v2);

    // display results
    for(auto&& i: v1)
        std::cout << i << '\n';
}

輸出:

1
3
4
7

毫無疑問,以上答案是有效的解決方案,但我無法讓它們進行編譯。 我是C ++初學者,還沒有研究通用用法,但是編譯器抱怨每個解決方案中的方括號([])。 我最終寫了自己的解決方案。 我確信它將使c ++獸醫感到畏縮,但它似乎可以工作。 這里是。

#include <vector>

void removeAll(std::vector<int>& original, const std::vector<int>& partition1){ 
for (int i=0; i<original.size();i++) {
    for (int x: partition1) {
        if (x == original[i]){
           original.erase(original.begin() + i);
           --i;
           break;
        }
     }
  }
}

C ++中沒有針對std::vector 與其他建議的實現方式不同,一種具有良好運行時的方法是將第二個集合轉換為std::setstd::unordered_set ,並迭代第一個向量,僅保留不屬於該元素的元素到集合,類似於:

template <class T>
void removeAll(std::vector<T>& in, const std::vector<T>& removeWhat) {
    std::set<T> st(removeWhat.begin(), removeWhat.end());
    size_t newSize = 0;
    for (size_t i = 0; i < in.size(); ++ i) {
        if (0 == st.count(in[i])) {
            in[newSize ++] = in[i];
        }
    }
    in.resize(newSize);
}

但這僅在您的T運算符<重載(對std::set要求)時有效。 它用於整數,因此將在您的特定情況下工作。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM