Например, std::string line{"\tSplit \t\t эта последовательность\t токенов "}; необходимо разделить на Split,
Код: Выделить всё
this,sequence,of,tokensЭто хорошо известная проблема, и можно найти множество реализаций:
- с помощью std::isstream
- с помощью std::regex
- с помощью std::strtok
- с помощью find или find_first_of
Код: Выделить всё
std::strtokИспользование find довольно простое и быстрое (см. тесты ниже), но код довольно многословен (я знаю, это субъективно).
Я хочу протестировать более современные, более читабельные и, надеюсь, более эффективные способы использования std::ranges.
Естественный путь кажется таким: через std::view::split, но он поддерживает только один разделитель. В этом случае быстрый поиск в Интернете возвращает такую реализацию:
Код: Выделить всё
auto tokenize_with_ranges(std::string const& str) {
auto tokens = str | std::views::split(' ') |
std::views::filter([](auto&& rng) { return !rng.empty(); }) |
std::views::transform([](auto&& rng) {
return std::string_view(rng.begin(), rng.end());
});
std::vector token_vector;
for (auto const token : tokens) {
token_vector.push_back(token);
}
return token_vector;
}
Но чтобы добавить второй разделитель, я разработал его сам и не смог добиться лучшего, чем:
Код: Выделить всё
auto tokenize_with_ranges(std::string const& str) {
auto tokens =
str | std::views::split('\t') |
std::views::transform([](auto&& tokens_splitted_on_tab) {
return tokens_splitted_on_tab | std::views::split(' ') |
std::views::filter([](auto&& rng) { return !rng.empty(); }) |
std::views::transform([](auto&& rng) {
return std::string_view(rng.begin(), rng.end());
});
}) |
std::views::join;
std::vector token_vector;
for (auto const token : tokens) {
token_vector.push_back(token);
}
return token_vector;
}
Я думаю, что это нелегко читать и невозможно масштабировать, если я хочу добавить другие разделители.
Есть ли способ преодолеть ограничение std::view::split и использовать диапазоны для разделения строки с разными разделителями?
Дополнительный контекст: сравнение
Я быстро установил тест (надеюсь, что не допустил ошибок), получив следующий рейтинг (с ускорением):
1000 строк размером 500
Код: Выделить всё
std::regexОбновление: сравнительный анализ с предоставленными ответами
https://quick-bench.com/q/ldP17PIGJ7a22m3hHR4v44QXeFU
1000 строк размером 100
Код: Выделить всё
std::regexПодробнее здесь: https://stackoverflow.com/questions/798 ... ing-stdran
Мобильная версия