Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/137.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 从范围中删除图元并将删除的图元复制到新范围_C++ - Fatal编程技术网

C++ 从范围中删除图元并将删除的图元复制到新范围

C++ 从范围中删除图元并将删除的图元复制到新范围,c++,C++,我需要一种方法从一个范围中移除满足特定条件的所有元素,在这种特殊情况下是std::vector,并将这些移除的元素复制到一个新的范围中,例如std::remove_if和一个输出参数。此操作后的输入范围顺序和输出范围顺序都不相关 一种简单的方法是使用std::partition查找所有邪恶元素,然后复制这些元素并最后删除它们,但这将在不需要的情况下两次接触所有邪恶元素 或者,我也可以自己编写所需的remove_if变体,但为什么要重新发明wheel plus呢?我不知道我是否能够达到高质量库实现

我需要一种方法从一个范围中移除满足特定条件的所有元素,在这种特殊情况下是std::vector,并将这些移除的元素复制到一个新的范围中,例如std::remove_if和一个输出参数。此操作后的输入范围顺序和输出范围顺序都不相关

一种简单的方法是使用std::partition查找所有邪恶元素,然后复制这些元素并最后删除它们,但这将在不需要的情况下两次接触所有邪恶元素

或者,我也可以自己编写所需的remove_if变体,但为什么要重新发明wheel plus呢?我不知道我是否能够达到高质量库实现的效率

因此,问题是:

这样的函数是否已经存在? Boost是允许的,但标准C++是首选的项目不依赖于Boost。
如果不是的话,有没有一种智能算法比简单的手工删除更快呢?

没有。有些函数可以删除与谓词匹配的元素,或者复制与谓词匹配的元素,但不能同时删除两者。但我们很容易通过两个步骤编写自己的:

template <typename InputIter, typename OutputIter, typename UnaryPredicate>
InputIter remove_and_copy(InputIter first, InputIter last,
                     OutputIter d_first, UnaryPredicate pred)
{
    std::copy_if(first, last, d_first, pred);
    return std::remove_if(first, last, pred);
}
或者编写自己的循环:

template <typename T, typename UnaryPredicate>
void remove_and_copy(std::vector<T>& from, std::vector<T>& to, UnaryPredicate pred)
{
    for (auto it = from.begin(); it != from.end(); ) {
        if (pred(*it)) {
            to.push_back(*it);
            it = from.erase(it);
        }
        else {
            ++it;
        }
    }
}

使用迭代器时删除的问题是,您没有访问实际容器的权限,因此实际上无法删除元素。相反,例如,std::remove所做的是将目标范围移动到范围的末尾,容器稍后将使用该范围来实际删除元素

相反,您可以让函数将流作为参数,以便在找到目标值后调用其删除方法:


include

可能重复的@IdeaHat My evil elements不需要相邻。@0x499602D2可能我读取的引用错误,但这不是只复制了所有我不需要复制的好元素,而不修改输入范围吗?它说它复制的元素不满足某个谓词,但它实际上并没有从原始容器中删除元素。糟糕的是@0x499602D2删除\u copy,如果名称非常糟糕,则删除\u copy\u。这是不可能的!这真的很像copy_if_not…,在整个范围内迭代两次,遗憾的是,我不认为这比我提到的std::partition方法更可取。@BaummitAugen取决于相对开销,但如果写比读慢,这会更快。分区方法最多需要最后一次/2次交换*3次写入/swap+邪恶计数写入。Barry将需要2*evil_count写入,写入的目的地将永远不需要保留,因此您不需要交换。这也将是稳定的,而分区则不会。然而,衡量将是证明这一论点的唯一真正方法。一如既往地衡量一切是的,无论如何我都需要这样做,我只是希望有人已经为我做了。与num_邪恶相比,范围相当长,但交换当然也不是免费的。我会看到…@BaummitAugen如果使用algos比稳定分区慢我会很惊讶。。。但是你可以编写自己的循环。更新了我的答案。@Barry是的,我会在这个周末的某个时候测量它。顺便说一下,我不需要稳定。你的循环是错误的。您将跳过c中的第一个元素,然后如果最后一个元素满足pred,您将从末尾走过去。@Barry,谢谢。修正了。第一部分,是的,不是第二部分。我看不出第二部分是如何不满足的。如果它是最后一个元素,并且满足pred,那么您将检查pred*endc。
template <typename T, typename UnaryPredicate>
void remove_and_copy(std::vector<T>& from, std::vector<T>& to, UnaryPredicate pred)
{
    std::copy_if(from.begin(), from.end(), std::back_inserter(to), pred);
    from.erase(std::remove_if(from.begin(), from.end(), pred), from.end());
}
template <typename T, typename UnaryPredicate>
void remove_and_copy(std::vector<T>& from, std::vector<T>& to, UnaryPredicate pred)
{
    for (auto it = from.begin(); it != from.end(); ) {
        if (pred(*it)) {
            to.push_back(*it);
            it = from.erase(it);
        }
        else {
            ++it;
        }
    }
}
remove_and_copy(v, u, [](int i) { return i%2 == 0; });