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

C++ ranges是否支持views::flat?与JS数组扁平化对比

C++ Ranges 实现数组扁平化问题解答

1. 扁平化vector<vector<int>>的管道函数

针对你提到的vector<vector<int>>扁平化需求,C++20 Ranges库提供的是**std::views::join**(不存在views::flat这个名称的适配器),代码可修改为:

#include <vector>
#include <ranges>

int main() {
    const std::vector<std::vector<int>> vv = {{0,1},{2,3}};
    auto rg = vv | std::views::join;
    // 遍历rg会依次得到0、1、2、3
    for (int num : rg) {
        // 处理元素逻辑
    }
}

std::views::join的作用就是将嵌套范围(如容器的容器)展开为单层元素序列,完全满足该场景需求。

2. 类似JavaScript flat(n)的多层嵌套扁平化

JavaScript的flat(n)支持指定嵌套深度,且因JS数组可存储混合类型,能处理[0,[1,[2,3]]]这类不同深度的混合嵌套结构,但C++是静态类型语言,无法直接处理混合类型的嵌套容器(除非借助std::variant或多态,但逻辑复杂度远高于JS的动态特性)。

固定深度的同类型嵌套

如果是固定深度的同类型嵌套(如vector<vector<vector<int>>>),可通过多次调用views::join实现对应深度的扁平化:

#include <vector>
#include <ranges>

int main() {
    const std::vector<std::vector<std::vector<int>>> vvv = {{{0}, {1}}, {{2,3}}};
    // 扁平化2层,得到单层int序列
    auto rg = vvv | std::views::join | std::views::join;
}

任意深度的递归扁平化

C++标准库没有直接提供类似flat(Infinity)的递归扁平化视图,但可自定义递归范围适配器,核心逻辑是判断元素是否为可迭代范围,若是则递归展开,否则直接输出元素(仅支持同类型嵌套):

#include <vector>
#include <ranges>
#include <concepts>
#include <iterator>

namespace my_views {
    template<std::ranges::input_range R>
    requires (!std::same_as<std::ranges::range_value_t<R>, R> && 
              std::ranges::input_range<std::ranges::range_value_t<R>>)
    struct recursive_join_view : std::ranges::view_interface<recursive_join_view<R>> {
        R base_;

        recursive_join_view(R base) : base_(std::move(base)) {}

        struct iterator {
            using base_iterator = std::ranges::iterator_t<R>;
            using inner_iterator = std::ranges::iterator_t<std::ranges::range_value_t<R>>;
            using value_type = std::ranges::range_value_t<std::ranges::range_value_t<R>>;

            base_iterator base_it_;
            base_iterator base_end_;
            inner_iterator inner_it_;
            inner_iterator inner_end_;

            iterator(base_iterator it, base_iterator end) : base_it_(it), base_end_(end) {
                if (base_it_ != base_end_) {
                    auto& inner_range = *base_it_;
                    inner_it_ = std::ranges::begin(inner_range);
                    inner_end_ = std::ranges::end(inner_range);
                    advance_to_valid();
                }
            }

            void advance_to_valid() {
                while (base_it_ != base_end_ && inner_it_ == inner_end_) {
                    ++base_it_;
                    if (base_it_ != base_end_) {
                        auto& inner_range = *base_it_;
                        inner_it_ = std::ranges::begin(inner_range);
                        inner_end_ = std::ranges::end(inner_range);
                    }
                }
            }

            value_type& operator*() const { return *inner_it_; }
            iterator& operator++() {
                ++inner_it_;
                advance_to_valid();
                return *this;
            }

            bool operator==(const iterator& other) const {
                return base_it_ == other.base_it_ && (base_it_ == base_end_ || inner_it_ == other.inner_it_);
            }
        };

        iterator begin() { return iterator(std::ranges::begin(base_), std::ranges::end(base_)); }
        iterator end() { return iterator(std::ranges::end(base_), std::ranges::end(base_)); }
    };

    struct recursive_join_adaptor {
        template<std::ranges::input_range R>
        requires std::ranges::input_range<std::ranges::range_value_t<R>>
        auto operator()(R&& r) const {
            return recursive_join_view<std::views::all_t<R>>(std::views::all(std::forward<R>(r)));
        }
    };

    inline constexpr recursive_join_adaptor recursive_join;
}

// 使用示例
int main() {
    std::vector<std::vector<std::vector<int>>> vvv = {{{0}, {1}}, {{2,3}}};
    auto rg = vvv | my_views::recursive_join;
}

注意:该自定义适配器仅支持同类型嵌套,无法处理JS那样的混合类型数组。

总结

  • 单层嵌套容器(如vector<vector<int>>):使用标准库std::views::join即可,无views::flat适配器。
  • 固定深度同类型嵌套:多次调用views::join实现对应深度扁平化。
  • 任意深度递归扁平化:标准库无直接支持,需自定义范围适配器,且仅能处理同类型嵌套结构。

内容的提问来源于stack exchange,提问作者Ludovic Aubert

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.18 20:05:34