You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

在constexpr上下文中从std::views::split获取最后元素的更优方法?

问题:在constexpr上下文中,从std::views::split的结果中获取最后元素是否有更优方法?

鉴于split视图的接口有一定限制性,我想到了如下实现方案,但该方案需要遍历所有元素,并非理想选择。

#include <ranges>
#include <iostream>
#include <vector>
#include <algorithm>

constexpr std::string_view lastdot(std::string_view input) {
    std::string_view delim{"."};
    std::string_view out;
    
    auto words = std::views::split(input, delim);

    std::size_t numwords = 0;

    std::ranges::for_each(words, [&](const auto word){
        numwords++;
    });

    std::size_t counter = 1;
    std::ranges::for_each(words, [&](auto word){
        if(counter == numwords)
            out = std::string_view{word.begin(), word.end()};
        counter++;
    });

    return out;
}

int main()
{
    constexpr auto out = lastdot("abc.def.ghi.jkl");
    std::cout << out << '\n';
}

更优实现方案

你的当前实现需要两次遍历split视图,效率确实不高。这里提供两种更优方案:

方案一:直接定位最后一个分隔符(最优)

不需要借助std::views::split,直接在原字符串中找最后一个分隔符的位置,操作更直接高效,且完全支持constexpr:

#include <iostream>
#include <string_view>

constexpr std::string_view lastdot(std::string_view input) {
    const auto pos = input.find_last_of('.');
    // 无分隔符则返回原字符串,否则返回分隔符后的部分
    return pos == std::string_view::npos ? input : input.substr(pos + 1);
}

int main()
{
    constexpr auto out1 = lastdot("abc.def.ghi.jkl");
    constexpr auto out2 = lastdot("no_dot_here");
    constexpr auto out3 = lastdot("trailing.dot.");
    
    std::cout << out1 << '\n'; // 输出 jkl
    std::cout << out2 << '\n'; // 输出 no_dot_here
    std::cout << out3 << '\n'; // 输出空字符串
}

方案优势

  • 时间复杂度O(n):仅一次遍历原字符串,比原方案的两次遍历开销减半。
  • 代码简洁直观:去掉冗余的split视图与两次循环,逻辑清晰。
  • 完全兼容constexpr:find_last_of和substr均支持constexpr上下文。

方案二:单次遍历split视图(基于split的优化)

如果必须依赖std::views::split,可以只遍历一次视图,实时更新最后一段的内容:

#include <ranges>
#include <iostream>
#include <string_view>

constexpr std::string_view lastdot(std::string_view input) {
    std::string_view delim{"."};
    std::string_view last_segment;
    
    for (auto segment : input | std::views::split(delim)) {
        last_segment = std::string_view(segment.begin(), segment.end());
    }
    
    return last_segment;
}

int main()
{
    constexpr auto out = lastdot("abc.def.ghi.jkl");
    std::cout << out << '\n';
}

这个方案仅需一次遍历split视图,比原方案高效,但仍不如直接定位分隔符的方案——因为split本身需要遍历整个字符串完成分割,额外增加了开销。


内容的提问来源于stack exchange,提问作者1lumin

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.22 06:32:06