在 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::any
,std::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<int>
不会有歧义,因为int
不能从任何std::initializer_list<T>
构造,但对于某些其他类型可能会产生歧义。以上是关于在 C++ 中创建嵌套列表的最佳方法是啥?的主要内容,如果未能解决你的问题,请参考以下文章
在 C++ 中创建同时支持 Unicode 和 ASCII 的库的最佳实践是啥?