【问题标题】:How to break up a string into a vector fast?如何快速将字符串分解为向量?
【发布时间】:2020-07-31 18:22:31
【问题描述】:

我正在处理 CSV 并使用以下代码来处理一行。

play with code

std::vector<std::string> string_to_vector(const std::string& s, const char delimiter, const char escape) {
  std::stringstream sstr{s};
  std::vector<std::string> result;
  while (sstr.good()) {
    std::string substr;
    getline(sstr, substr, delimiter);
    while (substr.back() == escape) {
      std::string tmp;
      getline(sstr, tmp, delimiter);
      substr += "," + tmp;
    }
    result.emplace_back(substr);
  }
  return result;
}

它的作用: 函数根据delimiter 分解字符串s。如果分隔符用escape 转义,则分隔符将被忽略。

此代码有效,但速度非常慢。 如何加快速度?

你知道任何现有的 csv 处理实现可以完全做到这一点并且我可以使用吗?

【问题讨论】:

  • FWIW,您应该将 getline(sstr, substr, delimiter) 移动到 while 条件中,而不是使用 sstr.good()。您应该始终使用读取操作来控制读取循环。更多信息:stackoverflow.com/questions/5605125/…
  • while (sstr.good()) 不太好。
  • 您可以将movesubstr 放入结果向量中
  • "如何加快速度?" - 使用编译器优化启用编译你的代码是显而易见的第一个建议(注意:这通常不是你构建代码时的默认设置,你需要采取明确的步骤来这样做)。
  • result.emplace_back(std::move(substr));

标签: c++ string performance csv stringstream


【解决方案1】:

做某事最快的方法就是完全不做。

如果您可以确保您的源字符串 s 将比使用返回的向量更有效,您可以将您的 std::vector&lt;std::string&gt; 替换为 std::vector&lt;char*&gt;,这将指向每个子字符串的开头。然后用零替换已识别的分隔符。

[编辑] 我还没有升级到 C++17,所以我没有string_view :)

注意:典型的 CSV 与您所暗示的不同;它不对逗号使用转义,而是用双引号将带有逗号的条目括起来。但我假设你知道你的数据。

实施:

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

std::vector<char*> string_to_vector(std::string& s, 
                                    const char delimiter, const char escape) 
{
  size_t prev(0), pos(0), from(0);
  std::vector<char*> v;
  while ((pos = s.find(delimiter, from)) != s.npos)
  {
    if (pos == 0 || s[pos - 1] != escape)
    {
      s[pos] = 0;
      v.push_back(&s[prev]);
      prev = pos + 1;
    }
    from = pos + 1;
  }
  v.push_back(&s[prev]);
  return v;
}

int main() {
  std::string test("this,is,a\\,test");
  std::vector<char*> v = string_to_vector(test, ',', '\\');

  for (auto& s : v)
    std::cout << s << " ";
}

【讨论】:

  • 更多 C++:使用 std::string_view 代替 char*。
  • 你们能否提供完整的示例。 AFAIK string_views 只是 char* 具有 size 属性。所以两者都应该没问题
  • 有了string_view,就不用修改原来的字符存储了。
  • char*std::string_view 的问题在于分配/存储策略:如何分配数据以及谁是所有权?返回std::vector&lt;std::string_view&gt;std::vector&lt;char*&gt; 乍一看似乎很棒,但程序员有责任确保所有std::string_view/char* 不会超过指向的字符数组。由于在此实现中分隔符并不总是“,”(参见连接),因此只要使用向量,就必须分配新数据并将其存储在某处。
  • @MarkRansom 当然,但生成的类型将与原始要求完全不同(这可能不是要求)。我主要想指出,要创建的大字符串远非免费。我想知道这是否比为字符串添加自定义分配器要快得多,避免使用std::move 复制并使用比std:stringstream 更快的东西解析字符串(基于原始代码)。话虽这么说,这是一种有趣的方法!
猜你喜欢
  • 1970-01-01
  • 2020-02-28
  • 1970-01-01
  • 1970-01-01
  • 2015-06-19
  • 2021-12-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多