Pau*_*aul 27 c++ string performance boost split
我在StackOverflow上调查了一段时间,找到了很好的算法来将带有多个分隔符的字符串拆分成一个vector< string >.我还发现了一些方法:
推动方式:
boost::split(vector, string, boost::is_any_of(" \t"));
的getline方法:
std::stringstream ss(string);
std::string item;
while(std::getline(ss, item, ' ')) {
    vector.push_back(item);
}
Boost的标记化方式:
char_separator<char> sep(" \t");
tokenizer<char_separator<char>> tokens(string, sep);
BOOST_FOREACH(string t, tokens)
{
   vector.push_back(t);
}
和酷STL方式:
     istringstream iss(string);
     copy(istream_iterator<string>(iss),
     istream_iterator<string>(),
     back_inserter<vector<string> >(vector));
和Shadow2531的方法(参见链接主题).
他们中的大多数来自这个主题.但不幸的是他们没有解决我的问题:
Boost的分裂很容易使用,但是大数据(在最好的情况下大约1.5*10 ^ 6单个元素)和大约10个分隔符我使用它的可怕的慢.
的getline,STL和Shadow2531的方法有,我只能用一个单个字符作为分隔符的问题.我需要更多.
在速度方面,Boost的标记化更加可怕.用10个分隔符花了11秒钟将一个字符串分成1.5*10 ^ 6个元素.
所以我不知道该怎么做:我希望有一个非常快速的字符串拆分算法和多个分隔符.
Boost的分裂最大还是有办法更快地完成它?
Pab*_*blo 33
我想到两件事:
find使用分隔符字符.以下是应用这些想法的快速尝试:
#include <vector>
#include <bitset>
#include <iostream>
#include <boost/algorithm/string/split.hpp>
#include <boost/algorithm/string/classification.hpp>
#include <boost/timer.hpp>
using namespace std;
size_t const N = 10000000;
template<typename C>
void test_custom(string const& s, char const* d, C& ret)
{
  C output;
  bitset<255> delims;
  while( *d )
  {
    unsigned char code = *d++;
    delims[code] = true;
  }
  typedef string::const_iterator iter;
  iter beg;
  bool in_token = false;
  for( string::const_iterator it = s.begin(), end = s.end();
    it != end; ++it )
  {
    if( delims[*it] )
    {
      if( in_token )
      {
        output.push_back(typename C::value_type(beg, it));
        in_token = false;
      }
    }
    else if( !in_token )
    {
      beg = it;
      in_token = true;
    }
  }
  if( in_token )
    output.push_back(typename C::value_type(beg, s.end()));
  output.swap(ret);
}
template<typename C>
void test_strpbrk(string const& s, char const* delims, C& ret)
{
  C output;
  char const* p = s.c_str();
  char const* q = strpbrk(p+1, delims);
  for( ; q != NULL; q = strpbrk(p, delims) )
  {
    output.push_back(typename C::value_type(p, q));
    p = q + 1;
  }
  output.swap(ret);
}
template<typename C>
void test_boost(string const& s, char const* delims)
{
  C output;
  boost::split(output, s, boost::is_any_of(delims));
}
int main()
{
  // Generate random text
  string text(N, ' ');
  for( size_t i = 0; i != N; ++i )
    text[i] = (i % 2 == 0)?('a'+(i/2)%26):((i/2)%2?' ':'\t');
  char const* delims = " \t[],-'/\\!\"§$%&=()<>?";
  // Output strings
  boost::timer timer;
  test_boost<vector<string> >(text, delims);
  cout << "Time: " << timer.elapsed() << endl;
  // Output string views
  typedef string::const_iterator iter;
  typedef boost::iterator_range<iter> string_view;
  timer.restart();
  test_boost<vector<string_view> >(text, delims);
  cout << "Time: " << timer.elapsed() << endl;
  // Custom split
  timer.restart();
  vector<string> vs;
  test_custom(text, delims, vs);
  cout << "Time: " << timer.elapsed() << endl;
  // Custom split
  timer.restart();
  vector<string_view> vsv;
  test_custom(text, delims, vsv);
  cout << "Time: " << timer.elapsed() << endl;
  // Custom split
  timer.restart();
  vector<string> vsp;
  test_strpbrk(text, delims, vsp);
  cout << "Time: " << timer.elapsed() << endl;
  // Custom split
  timer.restart();
  vector<string_view> vsvp;
  test_strpbrk(text, delims, vsvp);
  cout << "Time: " << timer.elapsed() << endl;
  return 0;
}
使用GCC 4.5.1使用-O4标志启用使用Boost 1.46.1进行编译,得到:
注意:输出略有不同,因为我的自定义函数会丢弃空标记.但是,如果您决定使用它,您可以根据需要调整此代码.
| 归档时间: | 
 | 
| 查看次数: | 19611 次 | 
| 最近记录: |