我想将一些Perl代码更改为C ++。我需要知道如何在C ++中实现嵌套的Perl哈希。我认为STL是一个不错的选择,并使用了地图。借助map,我只能创建一个简单的hash,但我不知道如何创建嵌套的hash结构。
我的Perl哈希是这样的:
%foo = (
"bar1" => {
Default => 0,
Value => 0
},
"bar2" => {
Default => 2,
value => 5,
other => 4
}
)
我可以这样修改它:$foo{"bar1"}->{"Default"} = 15
。
如何使用STL在C ++中执行此操作?也许这是一个简单的问题,但我无法弄明白。
答案 0 :(得分:4)
您可能需要以下类型:
std::map< std::string, std::map<std::string, int> >
您可能需要使用struct
(或class
)代替。
struct Element {
int default;
int value;
int other;
Element(): default(0), value(0), other(0)
{ }
Element(int default_, int value_, int other_)
: default(default_)
, value(value_)
, other(other_)
{ }
};
int main() {
std::map<std::string, Element> elements;
elements["bar1"]; // Creates element with default constructor
elements["bar2"] = Element(2,5,4);
elements["bar3"].default = 5; // Same as "bar1", then sets default to 5
return 0;
}
答案 1 :(得分:2)
您可以使用std::map<key_t,std::map<key_t,value_t> >
嵌套哈希。
答案 2 :(得分:2)
正如Steve Townsend所指出的,std::map
在概念上是相似的,但具有不同的实现。
在C ++中创建嵌套容器有点冗长:
#include <tr1/unordered_map>
#include <iostream>
typedef std::tr1::unordered_map< std::string, int > Inner;
typedef std::tr1::unordered_map< std::string, Inner > Outer;
int main()
{
Outer foo;
Inner::value_type bar1_data[] = {
Inner::value_type("Default", 0),
Inner::value_type("Value", 0),
};
const size_t n_bar1_data = sizeof(bar1_data) / sizeof(*bar1_data);
foo["bar1"] = Inner(bar1_data, bar1_data + n_bar1_data);
Inner::value_type bar2_data[] = {
Inner::value_type("Default", 2),
Inner::value_type("value", 5),
Inner::value_type("other", 4),
};
const size_t n_bar2_data = sizeof(bar2_data) / sizeof(*bar2_data);
foo["bar2"] = Inner(bar2_data, bar2_data + n_bar2_data);
如perlref中所述,下标括号之间的箭头是可选的,因此您可以编写(注释以维护C ++程序的流程)
// $foo{"bar1"}{"Default"} = 15;
非常接近C ++:
foo["bar1"]["Default"] = 15;
为了更好地衡量,我们打印结果结构并从main
返回0:
for (Outer::const_iterator o = foo.begin(); o != foo.end(); ++o) {
std::cout << o->first << ":\n";
for (Inner::const_iterator i = o->second.begin(); i != o->second.end(); ++i)
std::cout << " - " << i->first << " => " << i->second << '\n';
}
return 0;
}
输出:
bar1: - Value => 0 - Default => 15 bar2: - Default => 2 - value => 5 - other => 4
注意:此玩具程序中的输入和输出具有相同的顺序,但不依赖于此行为!
如果您更喜欢使用boost::unordered_map
,请在程序顶部更改几行:
#include <boost/unordered_map.hpp>
typedef boost::unordered_map< std::string, int > Inner;
typedef boost::unordered_map< std::string, Inner > Outer;
答案 3 :(得分:0)
让我在问题中添加一些元信息。其他人提供了实际的工作代码样本。
除了是一种不同类型的容器(O(对于C ++映射的log(n)访问与通常为Perl哈希的O(1)),C ++映射和Perl哈希之间的主要区别在于静态与动态语言本身的类型区别。映射的模板参数清楚地指定键和值的类型,而对于Perl哈希,只有键具有已知类型(字符串)。值是标量,但是可以且通常包含任何类型的数据结构。因此,将C ++映射用于相当普通的Perl数据结构是非常麻烦的,例如:
{
foo => [qw(bar baz)],
quibble => {
lion => 'animal',
pine => 'plant',
},
count => 5,
}
这是一个实际的区别而不是概念区别,因为你总是可以定义一个包含任意内容的结构/类/类型(参见其他答案)。这只是更多的工作,最终使用起来非常麻烦。
只有在数据结构非常规则的情况下,才能使用map<string, map<string, Stuff> >
这样的简单模板类型。
答案 4 :(得分:0)
如何使用STL在C ++中执行此操作?也许这是一个简单的问题,但我无法弄明白。
使用Perl哈希的方式是模仿C / C ++ struct
的常用方法。
因此,我认为代码最接近的C ++转换是:
struct foobar {
int Default, value, other;
foobar(int Default_ = 0, int value_ = 0, int other_ = 0)
: Default(Default_), value(value_), other(other_)
{}
};
std::map< std::string, foobar > foo;
foo["bar1"] = foobar( 0, 0 );
foo["bar2"] = foobar( 2, 5, 4 );