从简单数组递归构建嵌套哈希

Ste*_*ieD 4 raku

收到:

my @list = <one two three>;

my %hash;
my $item1 = @list.shift;
%hash{$item1} = {$item1 => 1};

my $item2 = @list.shift;
%hash{$item1} = {$item2 => 1};

my $item3 = @list.shift;
%hash{$item1}{$item2} = {$item3 => 1};

say %hash;
Run Code Online (Sandbox Code Playgroud)

输出所需的数据结构:

{one => {two => {three => 1}}}
Run Code Online (Sandbox Code Playgroud)

显然,如果是递归的话会更好,所以我这样写:

sub get-hash(%parent-hash, $last-item, *@list) {
    my $item = @list.shift;
    %parent-hash{$last-item} = { $item => 1 };
    get-hash(%parent-hash{$last-item}, $item, @list) if @list;

    return %parent-hash<root>;
}

%hash = get-hash({}, 'root', @list2);

Run Code Online (Sandbox Code Playgroud)

输出:

{one => {two => {three => 1}}}
Run Code Online (Sandbox Code Playgroud)

虽然它有效,但感觉不优雅,尤其是必须将root参数传递给子函数然后将其删除。有什么建议么?

Jon*_*ton 9

在即将推出的 Raku 版本中,有一个巧妙的方法可以做到这一点:

use v6.e.PREVIEW;
my @list = <one two three>;
my %hash;
%hash{||@list} = 1;
say %hash;
Run Code Online (Sandbox Code Playgroud)

表示||您要将列表用作多维哈希键。

如果您想坚持使用当前发布的语言版本中的内容,您仍然可以直接调用该运算符,因为它只是缺少语法糖:

my @list = <one two three>;
my %hash;
postcircumfix:<{; }>(%hash, @list) = 1;
say %hash
Run Code Online (Sandbox Code Playgroud)

任何一种情况的输出都如您所愿:

{one => {two => {three => 1}}}
Run Code Online (Sandbox Code Playgroud)

  • 有关多维索引的文档位于 https://docs.raku.org/language/subscripts#Multiple_dimensions,但似乎没有提到也可以在哈希上使用它们。 (2认同)
  • 我怀疑 @JonathanWorthington 的意思是 ```%a{$i} 编译成 postcircumfix:&lt;{ }&gt;(%a, $i)``` 和 ```%a{$i;$j} 编译成 postcircumfix:&lt; {; }&gt;(%a, ($i, $j))``` (2认同)