【问题标题】:Remove even numbers from a vector in c++从C ++中的向量中删除偶数
【发布时间】:2022-12-21 04:47:42
【问题描述】:

有人可以帮我实现这个功能:假设我需要使用引用从向量中删除所有偶数:我可以这样做吗? push_back 正确还是我应该使用其他东西?

void evenRemoe(vector<int>& arr) {
    for(int i = 0; i < arr.size(); i++) {
        if(arr[i] % 2 != 0) {
            push_back(arr[i]);
        }  
    }
}

【问题讨论】:

  • 你为什么要你正在尝试的东西去掉
  • 不,push_back 是不对的(我希望你知道这一点,否则你不会使用它,现在也不会在这里)。您可能会发现 erase-remove-if idiom 值得一读。

标签: c++


【解决方案1】:

使用push_back添加元素,所以这是行不通的。

您可以将 std::erase_if 与仿函数(如 lambda 或其他充当一元谓词的函数)一起使用,以决定应删除哪些元素。

void evenRemoe(std::vector<int>& arr) {
    std::erase_if(arr, [](int i) { return i % 2 == 0; });
}

在 C++20 之前,您可以实现擦除-删除习惯用法

#include <algorithm>
void evenRemoe(std::vector<int>& arr) {
    arr.erase(std::remove_if(arr.begin(), arr.end(),
                             [](int i) { return i % 2 == 0; }),
              arr.end());
}

【讨论】:

  • 旁注:它不一定是 lambda。也可以使用常规函数。
  • @eerorika 是的,已更新
【解决方案2】:

push_backstd::vector的一个方法追加向量末尾的元素,而不是删除.您需要的是 erase 方法之一。

但是,在擦除正在迭代的向量的元素时应该小心。必须注意避免在删除元素时增加索引。

更好的方法是使用 std::remove_if 算法而不是自己迭代向量。

void evenRemove(vector<int>& arr) {
    auto it = std::remove_if(arr.begin(), arr.end(),
        [](int n) { return (n % 2) == 0; });
    arr.erase(it, arr.end());
}

尽管有这个名字,std::remove_if 实际上并不是去掉向量中的任何元素。相反,它将与谓词匹配的元素(在我们的例子中 - 所有偶数整数)移动到向量的末尾并返回指向第一个此类元素的迭代器。因此,要实际删除您需要调用 erase 的元素,迭代器表示包含偶数的向量的尾部。

【讨论】:

    【解决方案3】:

    不,push_back() 不是正确的用法。那是为了添加值,不删除他们。

    另外,您的代码实际上是在寻找奇怪的值,不甚至值。

    您可以使用 std::vector::erase() 删除单个值,例如:

    void evenRemoe(vector<int>& arr){
        for(size_t i = 0; i < arr.size();){
            if (arr[i] % 2 == 0){
                arr.erase(arr.begin()+i);
            }else{
                ++i;
            }
        }
    }
    

    或者,考虑通过 std::remove_if()std::vector::erase() 使用 Erase-Remove idiom,例如:

    #include <algorithm>
    
    void evenRemoe(vector<int>& arr){
        arr.erase(
            std::remove_if(arr.begin(), arr.end(),
                [](int value){ return (value % 2) == 0; }
            ),
            arr.end()
        );
    }
    

    或者,在 C++20 中,通过 std::erase_if(),例如:

    void evenRemoe(vector<int>& arr){
        std::erase_if(arr,
            [](int value){ return (value % 2) == 0; }
        );
    }
    

    【讨论】:

    • 原始代码中存在错误 - 即使是整数也是 (value % 2) == 0
    • @AndreySemashev 已修复,谢谢
    【解决方案4】:

    从 C++20 开始,您可以使用 std::erase_if() ,在 c++20 之前,擦除-删除习语曾经是这个问题的解决方案。

    v.erase(std::remove_if(v.begin(), v.end(), is_even), v.end());
    

    is_even 是一个函子

    【讨论】:

    • 这不是 Ted Lyngmo 已经建议的吗?
    【解决方案5】:

    使用迭代器从向量中删除多个元素。 请注意,当我们使用迭代器擦除时,它会失效。

    int main(){
            vector<int> vec={1,2,3,4,5,6,7,8,9};
            for(auto it=vec.begin();it!=vec.end();){
               if(*it%2==0)
                   vec.erase(it);
               else
                   it++;
            }
            for(auto i:vec){
                cout<<i<<" ";
            }
            return 0;
        }
    

    输出:1 3 5 7 9

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-10-09
      • 1970-01-01
      • 1970-01-01
      • 2018-05-28
      • 1970-01-01
      • 1970-01-01
      • 2013-07-02
      • 1970-01-01
      相关资源
      最近更新 更多