Raku:访问多维哈希值时遇到问题

Gar*_*t S 10 hash raku

我在访问二维哈希值时遇到问题。据我在网上了解到的情况,应该是这样的:%myHash{"key1"}{"key2"} #Returns value

但是,我收到错误:“类型数组不支持关联索引。”

这是一个最小的可重复示例

my %hash = key1-dim1 => key1-dim2 => 42, key2-dim1 => [42, 42];
say %hash{'key1-dim1'}{'key1-dim2'}; # 42
say %hash{'key2-dim1'}{'foo bar'};   # Type Array does not support associative indexing.
Run Code Online (Sandbox Code Playgroud)

这是另一个可重现的示例,但更长:

my @tracks = 'Foo Bar', 'Foo Baz';
my %count;
for @tracks -> $title {
        $_ = $title;
        my @words = split(/\s/, $_);
        if (@words.elems > 1) {
            my $i = 0;
            while (@words.elems - $i > 1) { 
                my %wordHash = ();
                %wordHash.push: (@words[$i + 1] => 1);
                %counts.push: (@words[$i] => %wordHash);
                say %counts{@words[$i]}{@words[$i+1]}; #===============CRASHES HERE================
                say %counts.kv;
                $i = $i + 1;
            }
        }
    }
Run Code Online (Sandbox Code Playgroud)

In my code above, the problem line where the 2-d hash value is accessed will work once in the first iteration of the for-loop. However, it always crashes with that error on the second time through. I've tried replacing the array references in the curly braces with static key values in case something was weird with those, but that did not affect the result. I can't seem to find what exactly is going wrong by searching online.

I'm very new to raku, so I apologize if it's something that should be obvious.

Val*_*kas 9

将第二个元素添加到哈希的同一部分后,该元素现在是一个数组。最好通过在崩溃前打印哈希值来查看这一点:

 say "counts: " ~  %counts.raku;
 #first time: counts: {:aaa(${:aaa(1)})}
 #second time: counts: {:aaa($[{:aaa(1)}, {:aaa(1)}])}
Run Code Online (Sandbox Code Playgroud)

方括号表示一个数组。

也许BagHash已经为您做了一些工作。另请参阅无边界乐集

my @tracks = 'aa1 aa2 aa2 aa3', 'bb1 bb2', 'cc1';
for @tracks -> $title {
    my $n = BagHash.new: $title.words;
    $n.raku.say;
}

#("aa2"=>2,"aa1"=>1,"aa3"=>1).BagHash
#("bb1"=>1,"bb2"=>1).BagHash
#("cc1"=>1).BagHash

Run Code Online (Sandbox Code Playgroud)


rai*_*iph 8

让我首先解释一下最小的例子:

my %hash = key1-dim1 => key1-dim2 => 42,
           key2-dim1 => [42, 42];

say %hash{'key1-dim1'}{'key1-dim2'}; # 42
say %hash{'key2-dim1'}{'key2-dim2'}; # Type Array does not support associative indexing.
Run Code Online (Sandbox Code Playgroud)

问题在于 关联的值key2-dim1本身不是哈希值,而是Array. Arrays (和所有其他Positionals)仅支持按位置索引- 按整数。它们支持通过关联建立索引——通过字符串或对象

希望这能解释这一点。另请参阅使用标签加上“类型数组不支持关联索引”来搜索 SO[raku]


您的较长示例在这一行抛出错误 - 不是立即,而是最终:

say %counts{...}{...}; # Type Array does not support associative indexing.
Run Code Online (Sandbox Code Playgroud)

哈希值%counts由上一行构造:

%counts.push: ...
Run Code Online (Sandbox Code Playgroud)

摘录文档Hash.push

  • 如果散列中已经存在一个键...旧值和新值都被放入Array

例子:

my %h  = a => 1;
%h.push: (a => 1);              # a => [1,1]
Run Code Online (Sandbox Code Playgroud)

现在考虑以下代码与文档中的示例具有相同的效果:

my %h;
say %h.push: (a => 1);          # {a => 1}
say %h.push: (a => 1);          # {a => [1,1]}
Run Code Online (Sandbox Code Playgroud)

请注意,第一个 .push结果a => 1如何产生哈希键的1值,而同一对中的第二个结果如何产生该键的值。a%h .push[1,1]a

您的代码中也发生了类似的事情。

在您的代码中,您将值推%wordHash入哈希@words[$i]的键中%counts

一次执行此操作时,与输入的键关联的结果值就是您推送的值 - 。这就像上面的第一次推送一样,从推送中得到与键关联的值。@words[$i]%counts%wordHash1a1

因为%wordHash它本身就是一个散列,所以您可以对其进行关联索引。所以%counts{...}{...}有效。

但是,第二次将值推送到同一个 %counts键时(即,当键为 时%counts{@words[$i]},设置为已由保存的@words[$i]单词/字符串/键),则与该键关联的值最终不会与关联,而是相反,用.%counts%wordHash[%wordHash, %wordHash]

@tracks如果您输入的标题以相同的单词开头,那么您显然会在代码中再次遇到这样的情况。(我认为即使重复不是第一个单词而是后面的单词,情况也是如此。但是我对你的代码太困惑了,无法确定确切的损坏组合是什么。而且对于我来说已经太晚了尝试理解它,特别是考虑到它似乎并不重要。)

因此,当您的代码随后求值时%counts{@words[$i]}{@words[$i+1]},它与[%wordHash, %wordHash]{...}. 这是没有意义的,所以你会得到你看到的错误。


希望上述内容对您有所帮助。

但我必须说,我既对您的代码感到困惑,又对您实际想要完成的任务感到好奇。

我知道你刚刚学习 Raku,你从这个 SO 中得到的东西可能已经足够你了,但是 Raku 有一系列很好的高级哈希,比如数据类型和功能,如果你描述你的内容我们的目标可能不仅仅是消除您和我们迄今为止一直在处理的 Raku 皱纹。

无论如何,欢迎来到 SO 和 Raku。:)


jjm*_*elo 5

嗯,这有点有趣又令人惊讶。如果您遵循其他问题,您就不会出错,但是,这是程序的修改版本:

my @tracks = ['love is love','love is in the air', 'love love love'];
my %counts;
for @tracks -> $title {
    $_ = $title;
    my @words = split(/\s/, $_);
    if (@words.elems > 1) {
        my $i = 0;
        while (@words.elems - $i > 1) {
            my %wordHash = ();
            %wordHash{@words[$i + 1]} = 1;
            %counts{@words[$i]} = %wordHash;
            say %counts{@words[$i]}{@words[$i+1]}; # The buck stops here
            say %counts.kv;
            $i = $i + 1;
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

请检查之前崩溃的线路。您看得出来差别吗?你使用 i 作为循环变量是一件(不)幸运的事情......i在 Raku 中是一个复数。所以它崩溃了,因为它无法使用复数来索引数组。你只是把$掉了。

您可以在 Raku 中使用无符号变量,只要它们不是 i、e 或任何其他已定义的常量。

正如 Lukas Valle 所说,我还做了一些更改,以更好地反映您正在构建 PairHash而不是 Pair 数组的事实。

  • 嗨@JJ。我希望你不介意,但我已经编辑了 Q,以便代码实际上产生 OP 所说的错误。 (3认同)