【问题标题】:Combining multiple for loops into one using the OR operator使用 OR 运算符将多个 for 循环合并为一个
【发布时间】:2015-06-16 13:28:49
【问题描述】:

这可能是一个简单的问题,但我无法让它发挥作用。我已经搜索并尝试了人们为 OR 运算符 || 提供的所有建议,但我的代码无法正确使用它。

所以这就是我所得到的:我的这部分代码查看一个向量(目前大约 20,000 个条目长,但以后将达到数百万个)并删除所有包含关键字的元素:“事件”、“ /event”、“rwgt”和“/rwgt”。当我使用四个 for 循环时,它工作得非常好,每个关键字一个,如下所示:

for (int j = 0; j< myvec.size()-1;j++) {

    if(myvec[j] == "  <event>") {    //erase all instances of "<event>"
        myvec.erase(myvec.begin()+j);
    }
}

for (int j = 0; j< myvec.size()-1; j++) {

    if(myvec[j] == "  </event>") {   //erase all instances of "</event>"
        myvec.erase(myvec.begin()+j);
    }
}

for (int j = 0; j< myvec.size()-1; j++) {

    if(myvec[j] == "  <rwgt>") {   //erase all instances of "<rwgt>"
        myvec.erase(myvec.begin()+j);
    }
}

for (int j = 0; j< myvec.size()-1; j++) {

    if(myvec[j] == "  </rwgt>") {   //erase all instances of "</rwgt>"
        myvec.erase(myvec.begin()+j);
    }
}

但是,这在计算上变得相当昂贵(现在只有 20,000 个条目需要几分钟;当我们达到数百万时我无法想象它!)所以我想将所有四个关键字组合成一个 for 循环使用|| (OR) 运算符,如下所示:

for (int j = 0; j< myvec.size()-1;j++) {

if(myvec[j] == "  <event>" || myvec[j]  == "  </event>" || myvec[j] == "  <rwgt>" || myvec[j] == "  </rwgt>") {  //erase all instances of "<event>"
    myvec.erase(myvec.begin()+j);
}
}

但是,这比原来的四个 for 循环花费的时间更长,并且最终给我一个分段错误(核心转储)错误,据我所知,这意味着向量现在不知何故为空。

有人对如何解决这个问题有任何想法吗?

提前致谢!

【问题讨论】:

  • 另外,如果您实际上是在解析一些 XML,请使用专门的解析器。
  • 请注意你写的代码有问题,会跳过一些元素。这是由于您删除了一个项目然后继续。例如,如果您擦除位置“4”处的某些内容,那么您将检查位置 5。但是,当您擦除位置 4 时,向量的其余部分将向上移动,将新内容放置在位置 4,但您不会对此进行检查...

标签: c++ if-statement for-loop


【解决方案1】:

您可以使用functorstd::remove_if() 来执行此操作。

#include <iostream>
#include <vector>
#include <string>
#include <algorithm>


struct removeTag
{
    bool operator()(const std::string& tag) const
    {
        return tag == "  <event>" || tag == "  </event>" || tag == "  <rwgt>" || tag == "  </rwgt>";
    }
};

int main()
{
    std::vector<std::string> data = { "  <event>", "  </event>", "  <rwgt>", "  </rwgt>" };
    auto it = std::remove_if(data.begin(), data.end(), removeTag());
    data.erase(it, data.end());
    std::cout << data.size();
    std::cin.get();
    return 0;
}

输出:

0

【讨论】:

  • 感谢您的意见!我尝试使用您提供的方法,但我的编译器不喜欢它,看来我需要安装 c++11 才能使其工作。猜猜这就是我接下来要做的!
  • 是的 std::vector&lt;std::string&gt; data = { " &lt;event&gt;", " &lt;/event&gt;", " &lt;rwgt&gt;", " &lt;/rwgt&gt;" }; 需要 C++11,因为它使用了初始化列表。
【解决方案2】:

使用擦除删除习语。

myvec.erase(
    std::remove_if(myvec.begin(), myvec.end(), [](std::string const &e) {
      return e == " blabla" || e == "blasd";
    }), myvec.end());

【讨论】:

    【解决方案3】:

    我试过你的代码,替换后效果很好

    for(int j = 0; j < myvec.size()-1; j++)
    

    for(int j = 0; j < myvec.size(); j++)
    

    myvec.erase(myvec.begin() + j);
    

    myvec.erase(myvec.begin() + j--);
    

    我的测试程序如下所示:

    #include <iostream>
    #include <string>
    #include <vector>
    
    using namespace std;
    
    int main()
    {
       vector<string> myvec = {"<event>", "nichts", "</event>", "<rwgt>", "</rwgt>"};
    
       for (int j = 0; j < myvec.size(); j++) {
    
           if(myvec[j] == "<event>" || myvec[j] == "</event>" || 
                 myvec[j] == "<rwgt>" || myvec[j] == "</rwgt>") {   
    
              myvec.erase(myvec.begin() + j--);
           }
       }
    
       for(int i = 0; i < myvec.size(); i++) {
          cout<<myvec[i]<<endl;
       }
       return 0;
    }
    

    【讨论】:

    • @khfrekek 此解决方案的效率低于其他两个答案中提供的解决方案,这就是您看到性能如此差的原因。思考(并了解)在这种情况下会发生什么,并且不要在实践中使用此代码。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-10-08
    • 1970-01-01
    • 1970-01-01
    • 2021-06-30
    • 2011-01-13
    • 2020-11-17
    相关资源
    最近更新 更多