如何从C ++中的向量中删除几乎重复的内容

时间:2014-04-22 23:45:35

标签: c++ vector duplicates duplicate-removal floating-accuracy

我有一个浮点数的std :: vector我想不包含重复项,但填充向量的数学运算不是100%精确。向量的值相差几百,但应视为相同的点。例如,其中一个值中有一些值:

...
X: -43.094505
X: -43.094501
X: -43.094498
...

从这样的矢量中删除重复项的最佳/最有效方法是什么。

7 个答案:

答案 0 :(得分:5)

首先使用std::sort对矢量进行排序。然后使用std::unique和自定义谓词删除重复项。

std::unique(v.begin(), v.end(), 
            [](double l, double r) { return std::abs(l - r) < 0.01; });
// treats any numbers that differ by less than 0.01 as equal

Live demo

答案 1 :(得分:1)

  1. 排序始终是良好的第一步。使用std::sort()

  2. 删除不够独特的元素:std::unique()

  3. 最后一步,请致电resize(),也可以shrink_to_fit()

  4. 如果您想保留订单,请在副本上执行前3个步骤(但省略收缩) 然后将std::remove_if与lambda一起使用,检查副本中是否存在元素(二进制搜索)(如果找到则不要忘记将其删除),并且仅在副本中找到元素。

答案 2 :(得分:0)

我说std::sort()它,然后逐个浏览并删除某个范围内的值。

你可以在同一个向量上有一个单独的写迭代器,在最后有一个resize操作 - 而不是为每个被移除的元素调用erase()或者为了提高性能和更小的内存使用而使用另一个目标副本。

答案 3 :(得分:0)

如果您的向量不能包含重复项,则使用std::set可能更合适。然后,您可以使用自定义比较对象将小变化视为无关紧要。

答案 4 :(得分:0)

我会做以下事情:

  1. 创建set<double>

  2. 循环浏览矢量或使用仿函数

  3. 舍入每个元素并插入集合

  4. 然后你可以用空矢量交换你的矢量

  5. 将集合中的所有元素复制到空载体

  6. 这种方法的复杂性将是n * log(n),但它更简单,可以在几行代码中完成。仅存储矢量,内存消耗将增加一倍。另外,set每个元素消耗的内存比向量略多。但是,您将在使用后销毁它。

    std::vector<double> v;
    v.push_back(-43.094505);
    v.push_back(-43.094501);
    v.push_back(-43.094498);
    v.push_back(-45.093435);
    
    std::set<double> s;
    
    std::vector<double>::const_iterator it = v.begin();
    for(;it != v.end(); ++it)
        s.insert(floor(*it));
    
    v.swap(std::vector<double>());
    v.resize(s.size());
    std::copy(s.begin(), s.end(), v.begin());
    

答案 5 :(得分:0)

嗨,你可以这样比较

bool isAlmostEquals(const double &f1, const double &f2)
{
  double allowedDif = xxxx;
  return (abs(f1 - f2) <= allowedDif);
}

但这取决于你的比较范围而双精度不在你身边

如果你的矢量被排序,你可以使用std :: unique作为谓词

答案 6 :(得分:0)

到目前为止,大多数答案的问题在于你有一个不寻常的平等&#34;。如果A和B相似但不相同,则要将它们视为相等。基本上,A和A + epsilon仍然相等,但A + 2 * epsilon没有(对于某些未指定的epsilon)。或者,根据您的算法,A *(1 + epsilon)和A *(1 + 2 * epsilon)不会。

这确实意味着A + epsilon比较等于A + 2 * epsilon。因此,A = B和B = C并不意味着A = C.这打破了<algorithm>中的常见假设。

您仍然可以对值进行排序,这是一个明智的事情。但是你必须考虑如何处理结果中的大量类似值。如果范围足够长,则第一个和最后一个之间的差异仍然很大。没有简单的答案。