在C#中如果我想获取List List1
中的所有元素,这些元素不属于另一个List List2
,我可以
var result List1.Except(List2);
C ++中有std::vector
的等价物吗? (允许使用C ++ 11)
答案 0 :(得分:4)
以下使用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());});
答案 1 :(得分:3)
你需要编写自己的函数:
for (auto element : List1)
{
auto it = std::find(List2.begin(), List2.end(), element);
if(it == List2.end())
{
result.push_back(element);
}
}
答案 2 :(得分:1)
你应该考虑std :: list是否是正确的数据结构,至少在C ++中 - 默认情况下没有排序,所以在最坏的情况下你将不得不迭代size(list2)次list1的所有元素,使用Asha指出的算法。
更好的方法是使用有序的容器,例如multiset并使用std :: set_difference来创建结果。
答案 3 :(得分: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
。