簡體   English   中英

如何使用 substring 作為 unordered_set::erase 的鍵

[英]How to use a substring as key for unordered_set::erase

cplusplus.com 頁面關於 unordered_set 成員 function “erase ” 具有此示例代碼,可在提供精確匹配字符串時刪除集合元素“France”。

[編輯:我引用這段代碼是為了簡潔明了。 我的實際項目使用 unordered_set 的原因在此示例中不一定存在。 但是,適用於此示例代碼的解決方案將適用於我的項目。]

我將如何修改它以刪除與較小字符串匹配的所有元素?

例如,刪除所有以“F”作為第一個字符的元素。 [編輯:針對第一個字符只是一個例子。 ]

有什么方法可以訪問迭代器值來執行類似...

myset.erase( myset[當前正在評估的成員].substr(0,1)=="F")?

// unordered_set::erase
#include <iostream>
#include <string>
#include <unordered_set>

int main ()
{
  std::unordered_set<std::string> myset =
  {"USA","Canada","France","UK","Japan","Germany","Italy"};

  myset.erase ( myset.begin() );                    // erasing by iterator
  myset.erase ( "France" );                         // erasing by key
  myset.erase ( myset.find("Japan"), myset.end() ); // erasing by range

  std::cout << "myset contains:";
  for ( const std::string& x: myset ) std::cout << " " << x;
  std::cout << std::endl;

  return 0;
}

有什么方法可以訪問迭代器值來執行類似...

myset.erase(myset[當前正在評估的成員].substr(0,1)=="F")?

最簡潔的答案是不。 特別是對於一個無序的集合/映射,根據定義,它不會以任何特定的方式對其內容進行排序。 畢竟,這就是使它成為無序集/映射的原因。

您唯一的選擇是手動迭代集合或 map 中的所有鍵。 迭代不會以任何特定順序進行。 檢查每個鍵,如果它滿足規定的條件,則鍵及其值將從集合/映射中刪除。 這個邏輯必須手動實現。

在 C++20 中,無序映射/集合有一個erase_if()方法,在某種程度上有助於完成這項任務。 您提供適當的謂詞,它會完成所有工作。 但是,在場景下面,它仍然是這樣做的:迭代地圖/集,一次一個鍵。

沒有其他選擇。 沒有捷徑。 而且沒有辦法解決它。 這一切都歸結為無序容器在基本層面上的工作方式。 因此,當涉及到無序容器時,唯一的方法就是自己手動完成,一次一個鍵。

學習 C++ 的一部分是了解和理解每個容器的作用以及它是如何工作的。 如果擁有一個可以以合理優化的方式完成此操作的容器對您很重要,您不想使用無序集或 map。 也許您想使用不同的容器,這樣會做得更好。 另一個容器可能會做更糟糕的其他事情,這對你很重要,所以你必須選擇兩害相權取其輕,並做出明智的決定。

這就是為什么 C++ 庫有幾種不同類型的容器的原因。 它們都具有不同的結構,並且以根本不同的方式工作。 無序容器無法以最佳方式實現所描述的操作。

從 C++20 開始,標准庫中添加了一個名為std::erase_if()的算法,該算法專門用於標准庫中的每個數據結構。 假設某個謂詞為真,這可以在容器中的任何元素上調用容器.erase()方法。

該算法的效率取決於您要擦除的數據結構(更多詳細信息請參見下面鏈接的 cppreference 頁面)。

至於檢查字符串的第一個字母並以此為基礎進行擦除,您的謂詞可以是 lambda ,它使用 C++20 std::basic_string (又名std::string )字符串方法.starts_with()返回 boolean如果字符串以提供的 substring 開頭。 我制作了一個從您提供的使用這些實用程序的示例派生的Godbolt實例。

鏈接:

為此,您需要對字符串進行排序,即使用std::set而不是std::unordered_set 例如,如果你想刪除所有以“F”開頭的國家,你可以這樣做:

  std::set<std::string> myset =
  {"USA","Canada","France","UK","Japan","Germany","Italy", "Finland"};
 
  myset.erase ( myset.lower_bound( "F" ), myset.lower_bound( "G" ) );
 

活生生的例子

如果您需要以兩種方式訪問您的數據,您可以使用Boost.MultiIndex但這有一些學習曲線。

暫無
暫無

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

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