簡體   English   中英

如何從C ++中的向量中刪除幾乎重復的內容

[英]How to remove almost duplicates from a vector in C++

我有一個浮點數的std :: vector我想不包含重復項,但是填充向量的數學運算不是100%精確的。 向量的值相差幾百,但應視為相同的點。 例如,這里有一些值:

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

從這樣的向量中刪除重復項的最佳/最有效方法是什么。

首先使用std::sort矢量進行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

現場演示

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

  2. 刪除不夠獨特的元素: std::unique()

  3. 最后一步,調用resize() ,也可以shrink_to_fit()

如果要保留訂單,請在副本上執行前3個步驟(但省略收縮)。
然后使用帶有lambda的std::remove_if ,檢查副本中是否存在元素(二進制搜索)(如果找到則不要忘記將其刪除),並且只保留復制中找到的元素。

我說std::sort()它,然后逐個遍歷它並刪除一定范圍內的值。

您可以在同一個向量上有一個單獨的寫迭代器,在最后有一個調整大小操作 - 而不是為每個被刪除的元素調用erase()或者為了提高性能和更小的內存使用而使用另一個目標副本。

如果向量不能包含重復項,則使用std :: set可能更合適。 然后,您可以使用自定義比較對象將小更改視為無關緊要。

我會做以下事情:

  1. 創建一個set<double>

  2. 在循環中使用矢量或使用仿函數

  3. 圍繞每個元素並插入集合中

  4. 然后你可以用空向量交換你的向量

  5. 將集合中的所有元素復制到空向量

這種方法的復雜性將是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());

嗨,你可以這樣比較

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

但這取決於您的比較范圍,雙精度不在您身邊

如果您的向量已排序,您可以使用std :: unique作為謂詞

到目前為止,大多數答案的問題在於你有一個不同尋常的“平等”。 如果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>常見假設。

您仍然可以對值進行排序,這是一個理智的事情。 但是你必須考慮如何處理結果中的大量類似值。 如果范圍足夠長,則第一個和最后一個之間的差異仍然很大。 沒有簡單的答案。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM