在 C++ 中创建嵌套列表的最佳方法是啥?

Posted

技术标签:

【中文标题】在 C++ 中创建嵌套列表的最佳方法是啥?【英文标题】:What is the best way to make a nested list in C++?在 C++ 中创建嵌套列表的最佳方法是什么? 【发布时间】:2021-07-21 05:03:23 【问题描述】:

对于懂 Python 的人来说,最好的方式来解释我想要的是类比:

[1, [2, 3], 4, [5, [6]], 7]

显然,我可以实现 my own class (template) 来做到这一点,但如果标准库已经发明了这个***,我想避免 重新 - 发明它(或至少,避免将我半生不熟的重新发明版本放在我的项目中)。

【问题讨论】:

“最佳方式”似乎我们应该根据意见关闭。你只想要std::list<std::any>吗? 您有什么要求?你对“最好”的定义是什么?看来你已经有了实现,有什么问题? 来一个实际的例子来说明你为什么想要这个怎么样?上面的建议基本上是为您提供您所要求的,但这不是 C++ 中通常使用 的那种东西。 Pythonic 技术和数据结构往往不能很好地转换为 C++。 这是tree 的int 吗? 请根据您的要求提供一个真实世界的场景。详细说明您的要求。 【参考方案1】:

在底层,python 列表是一个动态重新分配的数组,即与std::vector 相同的东西,它的元素是动态的,即与std::any 相同的东西。所以这段代码最直接的类似物是

using p = std::vector<std::any>;

auto myList = p  1, p  2, 3 , 4, p  5, p  6  , 7;

【讨论】:

不错!我什么都不知道。但是,如果我希望所有“叶子”元素都属于同一类型(例如 int)怎么办? @allyourcode 你说的是树吗? @allyourcode:那么你所做的实际上与你引用的 python 示例非常不同,因为 python 也可以让你编写类似 [1.0, [ 2, 3], "四", [lambda x: 5, [6]], 7]. @allyourcode:也就是说,这是一个完全不同的问题 @allyourcode 的主要问题是:您是否关心在数组中嵌套数组的可能性,还是能够存储每种可能的类型(或两者兼而有之?)。因为有很多选项取决于您的确切要求:例如已经提到std::anystd::variant 也可以在这里工作。但在我看来,您正在寻找像树/图这样的自定义数据结构。如果是这样,您可以尝试boost。或者,根据您的具体要求,也许只需要std::(multi)set 就可以了。【参考方案2】:

因此,您的值的类型将包含 int 或相同类型的值向量。

这可以通过std::variant 来实现,该结构允许类型的递归性质(以及一个允许使用所需语法对其进行初始化的构造函数)

template<typename T>
struct nested_list : std::variant<std::vector<nested_list<T>>, T> 
    using std::variant<std::vector<nested_list<T>>, T>::variant;

    nested_list(std::initializer_list<nested_list> ilist)
        : std::variant<std::vector<nested_list<T>>, T>(
              std::in_place_index<0>, ilist) 

    // You can also add some helper methods like "get_vector", "is_vector", etc.
;

使用示例:

template<typename T>
std::ostream& operator<<(std::ostream& os, const nested_list<T>& lst) 
    if (auto* v = std::get_if<0>(&lst)) 
        os << '';
        bool first = true;
        for (const auto& child : *v) 
            if (first) first = false;
            else os << ", ";
            os << child;
        
        os << '';
     else if (auto* e = std::get_if<1>(&lst)) 
        os << *e;
     else 
        os << "<valueless by exception>";
    
    return os;


int main() 
    nested_list<int> x = 1, 2, 3, 4, 5, 6, 7;
    std::cout << x << '\n';

【讨论】:

哇!我很惊讶您可以让nested_list 继承自nested_list 派生的东西!对我来说,这是解决方案的主要关键。 我一直在尝试学习变体。我理解基本概念,但像 in_place_index 这样的东西让我感到困惑。我猜你说的是使用第一个(即两个中的索引 0)可能的类型,即 vector<...> ?我想这是需要的,否则它可能(或肯定是?)在初始化期间应该选择哪种类型变体不明确? @allyourcode 你对构造函数的作用是完全正确的。有关更多详细信息,请参阅此en.cppreference.com/w/cpp/utility/variant/variant(特别是第 7 个构造函数)。使用nested_list&lt;int&gt; 不会有歧义,因为int 不能从任何std::initializer_list&lt;T&gt; 构造,但对于某些其他类型可能会产生歧义。

以上是关于在 C++ 中创建嵌套列表的最佳方法是啥?的主要内容,如果未能解决你的问题,请参考以下文章

在 C++ 中创建同时支持 Unicode 和 ASCII 的库的最佳实践是啥?

在一个 CMake 项目中创建多个 rpm(deb)包的最佳方法是啥?

在 Laravel 5.4 中创建表单的最佳方法是啥?

在 C# 2.0 中创建向导的最佳方法是啥?

在 Objective-C 中创建常量的最佳方法是啥

PHP:在 yii 中创建更高级别的查询语言以创建条件过滤器的最佳方法是啥