3

在 C# 中,如果我想获取 aList List1中不属于另一个的所有元素,List List2我可以这样做

var result List1.Except(List2);

std::vectorC++ 中是否有与 s 等价的东西?(允许使用 C++11)

4

4 回答 4

6

下面将使用 List1 中不在 List2 中的内容填充 List3。我希望它是您正在寻找的:

std::vector<Type> List1, List2;
//
// populate List1 and List2
//

std::vector<Type> List3;
std::copy_if(List1.begin(), List1.end(), std::back_inserter(List3),
     [&List2](const Type& arg)
     { return (std::find(List2.begin(), List2.end(), arg) == List2.end());});

或者,这可能会更好地执行,因为您不必搜索整个列表来确定不存在。相反,您可以获得早期的“命中”,然后移动到下一个节点。注意谓词中的逻辑翻转:

std::vector<Type> List3;
std::remove_copy_if(List1.begin(), List1.end(), std::back_inserter(List3),
     [&List2](const Type& arg)
     { return (std::find(List2.begin(), List2.end(), arg) != List2.end());});
于 2013-04-02T08:02:02.623 回答
3

您需要编写自己的函数,如下所示:

for (auto element : List1)
{
  auto it = std::find(List2.begin(), List2.end(), element);
  if(it == List2.end())
  {
     result.push_back(element);
  }
}
于 2013-04-02T07:49:27.313 回答
1

您应该考虑 std::list 是否是正确的数据结构,因为它是 - 至少在 C++ 中 - 默认情况下未排序,因此在最坏的情况下,您将不得不迭代 size(list2) 次通过所有元素list1,使用像 Asha 指出的算法。

更好的方法是使用有序容器,例如 multiset 并使用 std::set_difference 来创建结果。

于 2013-04-02T08:06:43.627 回答
1

对于任意容器,您始终可以使用std::remove_if+container::erase组合:

    template <typename Cont, typename FwdIt>
    void subtract(Cont& cont, FwdIt first, FwdIt last) {
        using std::begin; using std::end;
        using const_reference = typename Cont::value_type const&;
        cont.erase(std::remove_if(begin(cont), end(cont),
            [first, last](const_reference value){
                return last != std::find(first, last, value);
             }), end(cont));
    }

    template <typename Cont1, typename Cont2>
    void subtract(Cont1& cont1, Cont2 const& cont2) {
        using std::begin; using std::end;
        subtract(cont1, begin(cont2), end(cont2));
    }

std::list你可以重载subtract函数的情况下,因为std::list有一个专用的remove_if成员函数:

    template <typename T, typename Alloc, typename FwdIt>
    void subtract(std::list<T, Alloc>& l, FwdIt first, FwdIt last) {
        l.remove_if([first, last](T const& value){
            return last != std::find(first, last, value);
        });
    }

    template <typename T, typename Alloc, typename Cont>
    void subtract(std::list<T, Alloc>& l, Cont const& cont) {
        using std::begin; using std::end;
        subtract(l, begin(cont), end(cont));

}

这些实现是通用的,不对序列的排序做任何假设。如果只保证您的第二个容器被排序,您可以使用std::binary_seach代替find. 如果两个序列都已排序,则应使用std::set_difference.

于 2013-04-02T08:35:57.213 回答