减去两个无顺序的std :: vector对象

时间:2015-10-01 10:54:26

标签: c++ c++11 vector

我有两个对象向量。类似的东西:

std::vector<thing> all_things;
std::vector<thing> bad_things;

我想获得包含 good_things 的第三个向量。换句话说, all_thing 中的每个对象都不属于 bad_things

std::vector<thing> good_things=subtract(all_things,bad_things);

有关如何以最有效和最标准的方式实施减去的任何想法。

P.S矢量可以 NOT 被排序,因为类事物没有任何要排序的东西。 谢谢!

编辑: 我不想对all_things做任何改动。 e.g。

void substract(const std::vector<thing>& a, const std::vector<thing>& b);

4 个答案:

答案 0 :(得分:2)

从评论中,您的thing可以按照无意义的方式进行排序。

没关系。

毫无意义地对它们进行排序。

编写一个函数,它接受两个thing s并给它们一个无意义的顺序,如果它们是相等的,那么两个东西只能相互比较。

调用此bool arb_order_thing(thing const&, thing const&)

现在std::sort两个向量并使用std::set_difference

现在,如果要复制的东西很昂贵,这可能会很昂贵。因此,创建两个thing const*向量,写bool arb_order_thing_ptr(thing const*, thing const*)(使用无意义排序进行解引用和比较),使用该向量对指针进行排序,使用set_difference,然后转换回{ {1}}。

或者,考虑编写vector<thing>哈希(不是thing const*,因为这是全局和粗鲁的)并使用std::hash<thing*>来手动完成工作。散列两个向量中较小的一个,然后对另一个向量的散列进行unordered_set<thing const*>测试。

答案 1 :(得分:1)

如果您无法订购,可以使用强力方式。只需比较矢量。 E.g:

std::vector<Thing> all;
std::vector<Thing> bad;
std::vector<Thing> good (all.size());
auto it = std::copy_if (all.begin(), all.end(), good.begin(), 
    [&bad](const Thing& t){return std::find(bad.begin(), bad.end(), t) == bad.end();} );
all.resize(std::distance(all.begin(),it));

答案 2 :(得分:1)

如果thing构建/复制费用昂贵而且容器很长且坏处很多,那么构建同样长的“不坏”并不是一个好主意。阵列。实际上,必须根据thing比较来填充all.size()x good.size()的标志矩阵。如果确保了单一性,那么可以避免迭代坏事。但O(N 2 )无论如何都是复杂的。

答案 3 :(得分:1)

我想建议类似于mkaes的代码,但几乎没有调整:

std::vector<thing> substract(const std::vector<thing>& a, const std::vector<thing>& b) {
    std::vector<thing> sub;
    sub.reserve(a.size());
    for (const auto &item : a) {
        if (std::find(b.begin(), b.end(), item) == b.end()) {
             sub.push_back(a);
        }
    }
    return sub;
}

这是你想要实现的残酷版本。但如果你不能对矢量元素进行排序,那么它是你能做的最好的。但请记住,您需要能够比较item类型的两个对象,这意味着您需要提供operator==