从两个向量中删除公共实体?

Posted

技术标签:

【中文标题】从两个向量中删除公共实体?【英文标题】:Remove the common entities from two vector? 【发布时间】:2009-03-13 07:06:59 【问题描述】:

说我有vector<class1a>,vector<class1b> 如何从它们中删除公共实体 我已经为 class1 对象 class1a,class1b 定义了 ==operator

【问题讨论】:

最终结果是什么?你想要一个合并的列表吗? 你是什么意思,没有1?你想要一个向量作为结果吗?你想保留这两个向量吗? 对不起...我只想要 2 个单独的向量 【参考方案1】:

stl algorithms 提供了几个函数来执行集合操作,特别是计算 set symmetric difference,这正是您所需要的。

这是一个使用示例:

#include <algorithm>
#include <vector>

int main(int argc, char **argv) 

    std::vector<int> v1;
    v1.push_back(1);
    v1.push_back(2);
    v1.push_back(3);
    v1.push_back(4);
    v1.push_back(5);
    v1.push_back(6);

    std::vector<int> v2;
    v2.push_back(2);
    v2.push_back(4);
    v2.push_back(6);
    v2.push_back(8);

    // Ranges must be sorted!
    std::sort(v1.begin(), v1.end());
    std::sort(v2.begin(), v2.end());

    std::vector<int> res; // Will contain the symmetric difference
    std::set_symmetric_difference(v1.begin(), v1.end(), 
                                  v2.begin(), v2.end(), 
                                  std::back_inserter(res));

    // Copy result to the output
    std::copy(res.begin(), res.end(), std::ostream_iterator<int>(cout, " "));
    // Prints "1 3 5"

    return 0;

std::set_symmetric_difference 需要两个范围(即两对 OutputIterators)和一个 InputIterator,它将放置结果。它还将一个迭代器返回到结果范围的末尾。


编辑

我刚刚就您的问题阅读了您的 cmets。如果想修改原来的两个向量,可以使用std::set_difference

vector<int>::iterator endRange;
endRange = set_difference(v1.begin(), v1.end(), 
                          v2.begin(), v2.end(), 
                          v1.begin());
v1.erase(endRange, v1.end());

这里,我们将集合差 v1 - v2 的结果放入 v1。但是,我们不能反之亦然,因为 v1 现在已修改。解决方法是计算v1和v2的交集,然后和这个交集的差std::set_intersection

vector<int> inter;
set_intersection(v1.begin(), v1.end(),
                 v2.begin(), v2.end(),
                 back_inserter(inter));
// inter is "2 4 6"

v1.erase(set_difference(v1.begin(), v1.end(),
                        inter.begin(), inter.end(),
                        v1.begin()),
         v1.end());
// v1 is "1 3 5"

v2.erase(set_difference(v2.begin(), v2.end(),
                        inter.begin(), inter.end(),
                        v2.begin()),
         v2.end());
// v2 is "8"

我想还有更多性能更高的解决方案,但是这个很清楚,并且通过使用广为人知的 stl 算法真正传达了您的意图。

【讨论】:

说你在向量值 10 中有一个条目 ...所以我必须得到 2 个向量,一个是 1,3,5,另一个是 10 算法是否对我在向量中使用的类施加任何约束 这些算法使用运算符<.>【参考方案2】:

在 stl 标头算法中有一个名为“set_symmetric_difference”的函数,它将把一个的所有元素,但不是两个源范围都放在一个目标范围中。

请记住,两个范围都必须开始排序。

msdn documentation

【讨论】:

【参考方案3】:

对这 2 个向量进行排序,然后并行遍历它们,执行常见的合并操作。这会告诉你哪些项目是相同的。

【讨论】:

【参考方案4】:

简单的方法是进行 n^2 次迭代,将第一个向量中的每个元素与第二个数组中的每个元素进行比较,并将任何匹配项添加到第三个向量中。完成 n^2 次迭代后,您将遍历第三个向量并从前两个向量中删除这些对象。

不是最好的解决方案,但取决于您期望向量的大小,它可能是最简单的解决方案之一。

【讨论】:

【参考方案5】:

对于class1aclass1b 中的每对项目,如果它们不相等,则将它们添加到输出集中。否则,只添加一个这样的实例。重复数组长度的最小值。如果一个更长,您将剩下一些 - 尝试将所有这些添加到集合中。

【讨论】:

【参考方案6】:

开始在Set中添加vector的值。覆盖 class1 和 class2 的 equals 方法来决定您希望对象如何相等。如果默认情况下不覆盖等于 == 将用于比较,并且由于对象不同 class== 将始终返回 false。所以你需要重写equals方法。

【讨论】:

以上是关于从两个向量中删除公共实体?的主要内容,如果未能解决你的问题,请参考以下文章

在 Clojure 中,如何合并两个地图向量?

从两个不同的实体中获取对象

将数据框中的两个混乱向量拆分为一个公共列

EFCode First:删除具有两个实体关联的值对象

查找两个字符串向量的交集

Hibernate:ManyToMany 反向删除