我希望得到一个数字std::string
但不使用循环(我自己;我正在调用的代码使用的是什么,我不介意).请求的另一种观点是:从字符串中删除所有非数字,只留下数字.我知道我可以使用以下代码查找字符串中的所有数字:
std::string get_digits(std::string input) {
std::string::size_type next_digit(0u);
for (std::string::size_type pos(0u);
input.npos != (pos = input.find_first_of("0123456789"));
++pos) {
input[next_digit++] = input[pos];
}
input.resize(next_digit);
return input;
}
Run Code Online (Sandbox Code Playgroud)
但是,此函数使用循环.std::string
不提供功能find_all()
或东西!理想情况下,字符串就地移动(上面的代码移动它,但很容易更改为参考).
当有多种选择时,我会保证发布不同方法在某些冗长文本上有多好的分析结果.
一种方法是使用std::copy_if
(或std::remove_if
):
std::string get_digits(std::string input) {
std::string result;
std::copy_if(
input.begin(),
input.end(),
std::back_inserter(result),
[](char c) { return '0' <= c && c <= '9'; });
return result;
}
Run Code Online (Sandbox Code Playgroud)
显然这在内部使用循环,但你说你不关心那个......
编辑:有std::remove_if
:
std::string get_digits_remove(std::string input) {
auto itErase = std::remove_if(
input.begin(),
input.end(),
[](char c) { return !('0' <= c && c <= '9'); });
input.erase(itErase, input.end());
return input;
}
Run Code Online (Sandbox Code Playgroud)
虽然我主要希望得到5个快速答案(没有实现,但感叹),答案和评论导致了一些我没有想过的有趣方法.我个人的期望是有效的答案会导致:
如果你想要快,请使用
input.erase(std::remove_if(input.begin(), input.end(),
[](unsigned char c){ return !std::isdigit(c); }),
input.end());
Run Code Online (Sandbox Code Playgroud)如果你想简洁,请使用
text = std::regex_replace(text, std::regex(R"(\D)"), "");
Run Code Online (Sandbox Code Playgroud)相反,有一些我甚至没有考虑过的方法:
使用递归函数!
使用std::partition()
似乎需要额外的工作(保留将被抛出的字符)并更改顺序.
使用std::stable_partition()
似乎需要更多工作,但不会改变顺序.
使用std::sort()
并提取具有相关字符的子字符串,虽然我不知道如何保留原始的字符序列.只是使用稳定版本并不完全.
将不同的方法放在一起并使用许多关于如何对字符进行分类的变体,导致总共17个版本的大致相同的操作(代码在github上).大多数版本的使用std::remove_if()
和std::string::erase()
,但在数字的分类有所不同.
remove_if()
与[](char c){ return d.find(c) == d.npos; })
.remove_if()
同 [](char c){ return std::find(d.begin(), d.end(), c) == d.end(); }
remove_if()
同 [](char c){ return !std::binary_search(d.begin(), d.end()); }
remove_if()
同 [](char c){ return '0' <= c && c <= '9'; }
remove_if()
with [](unsigned char c){ return !std::isdigit(c); }
(char
传递为unsigned char
避免未定义的行为,如果c
是char
负值)remove_if()
with std::not1(std::ptr_fun(std::static_cast<int(*)(int)>(&std::isdigit)))
(必须使用强制转换来确定正确的过载:std::isdigit()
恰好是过载).remove_if()
同 [&](char c){ return !hash.count(c); }
remove_if()
with [&](char c){ return filter[c]; }
(代码初始化实际上使用循环)remove_if()
同 [&](char c){ return std::isidigit(c, locale); }
remove_if()
同 [&](char c){ return ctype.is(std::ctype_base::digit, c); }
str.erase(std::parition(str.begin(), str.end(), [](unsigned char c){ return !std::isdigit(c); }), str.end())
str.erase(std::stable_parition(str.begin(), str.end(), [](unsigned char c){ return !std::isdigit(c); }), str.end())
copy_if()
其中一个答案中描述的方法text = std::regex_replace(text, std::regex(R"(\D)"), "");
(我没有设法让它在icc上工作)我在MacOS笔记本上运行了基准测试.由于这样的结果很容易用Google Chars绘制图形,因此这里是结果图表(虽然删除了使用正则表达式的版本,因为这些会导致图形缩放,使得有趣的位不可见).表格形式的基准测试结果:
test clang gcc icc
1 use_remove_if_str_find 22525 26846 24815
2 use_remove_if_find 31787 23498 25379
3 use_remove_if_binary_search 26709 27507 37016
4 use_remove_if_compare 2375 2263 1847
5 use_remove_if_ctype 1956 2209 2218
6 use_remove_if_ctype_ptr_fun 1895 2304 2236
7 use_remove_if_hash 79775 60554 81363
8 use_remove_if_table 1967 2319 2769
9 use_remove_if_locale_naive 17884 61096 21301
10 use_remove_if_locale 2801 5184 2776
11 use_partition 1987 2260 2183
12 use_stable_partition 7134 4085 13094
13 use_sort 59906 100581 67072
14 use_copy_if 3615 2845 3654
15 use_recursive 2524 2482 2560
16 regex_build 758951 531641
17 regex_prebuild 775450 519263
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
863 次 |
最近记录: |