【问题标题】:Delete strings in a vector删除向量中的字符串
【发布时间】:2012-02-02 23:22:37
【问题描述】:

我有一个充满字符串的向量

向量consistentWords包含4个字符串

  1. ddf
  2. edf
  3. 美联储
  4. hedf

现在我想删除所有单词不以字母d开头的字符串

但它最终只是删除了 eedf 和 hedf,我留下的结果是

  1. ddf
  2. 美联储

我的代码:

    for(int q=0; q<consistentWords.size(); q++)
    {
        string theCurrentWord = consistentWords[q];
        if(theCurrentWord[0] != 'd')
        {
            consistentWords.erase(consistentWords.begin()+q);
        }
    }

有什么想法吗?我只是不明白为什么它没有删除所有不以 d 开头的字符串。

【问题讨论】:

  • 您可能希望将theCurrentWord 设为引用以避免复制。

标签: c++ string vector


【解决方案1】:

首先,字符串对应于这些索引:

dedf 0
eedf 1
fedf 2
hedf 3

假设你删除了eedf(所以q == 1。删除后,向量看起来像

dedf 0
fedf 1
hedf 2

但随后q 增加到 2,完全跳过了fedf。解决方法是稍微改变for 循环:

for(int q=0; q<consistentWords.size();)
{
    string theCurrentWord = consistentWords[q];
    if(theCurrentWord[0] != 'd')
    {
        consistentWords.erase(consistentWords.begin()+q);
    }
    else
    {
        q++;
    }
}

或具有相同效果的东西。

【讨论】:

    【解决方案2】:

    您正在跳过元素。假设您需要删除元素 5,6: 当你删除元素 5 时,元素 6 变成元素 5 - 你跳过它,因为 q 增加到 6,

    更好的方法是仅在不删除元素时手动增加q

    【讨论】:

    • 即使使用迭代器,我们也必须小心。我记得当您从向量中删除时,访问该元素的迭代器变得无效。
    • 在遍历矢量或地图时要小心删除元素。正确的算法是不明显的,通常有几个细微之处。
    • 感谢 cmets。我从答案中删除了“迭代器”部分。
    【解决方案3】:

    问题是您正在从向量中删除元素并在同一迭代中增加索引q。所以在你的for循环的第二次迭代中,你从你的向量中删除"eedf"然后你的向量是["dedf", "fedf", "hedf"]q = 1。但是,当您循环回到 for 循环的开头时,q 会增加到 2,因此您接下来查看 "hedf",跳过 "fedf"。要解决此问题,您可以在从数组中删除元素时减少 q,如下所示:

    for(int q=0; q<consistentWords.size(); q++)
    {
        string theCurrentWord = consistentWords[q];
        if(theCurrentWord[0] != 'd')
        {
            consistentWords.erase(consistentWords.begin()+q);
            --q;
        }
    }
    

    或者你可以使用迭代器:

    vector<string>::iterator it = consistentWords.begin()
    while(it != consistentWord.end())
    {
        string theCurrentWord = consistentWords[q];
        if(theCurrentWord[0] != 'd')
        {
            it = consistentWords.erase(it);
        }
        else
        {
            ++it;
        }
    }
    

    请注意,erase 会返回一个迭代器,指向您已擦除的元素之后的元素。您必须重新分配it,因为它会在调整矢量大小时失效。

    【讨论】:

    • 正是我想要的。感谢您的详细解释和帮助。
    【解决方案4】:

    当你擦除你不应该做 q++。然后你会错过一个元素。

    【讨论】:

      【解决方案5】:

      问题已得到解答,但您应该查看Erase-remove idiom

      例子:

      consistentWords.erase(
          std::remove_if(consistentWords.begin(), consistentWords.end(), 
          [](const std::string& s) -> bool { return (s[0] == 'd'); }),
          consistentWords.end());
      

      【讨论】:

        【解决方案6】:

        删除单词:

        consistentWords.erase(
            std::remove(consistentWords.begin(), consistentWords.end(), theCurrentWord),
            consistentWords.end()
        );
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2011-12-02
          • 2011-11-03
          相关资源
          最近更新 更多