在 Raku 中将数字重新排列为非英文字母顺序

Lar*_*een 8 hash raku

我正在尝试将数字重新排列为非英文字母顺序。

my @numDE = < null eins zwei drei  vier fünf sechs sieben acht  neun >;
# english   < zero one  two  three four five six   seven  eight nine >;

my %numrank; # The lookup hash: number => its_alphabetical_order

for @numDE.sort.kv -> $k,$v {%numrank{%(@numDE.kv.reverse){"$v"}} = "$k"};

my %temp; # number => reassigned order value  
%temp{"$_"}= %numrank{"$_"} for "2378".comb; # 2378 sample input
say %temp.sort(*.values); # this prints:
# (8 => 0 3 => 1 7 => 7 2 => 9) it's in order but unformatted

my %target= %temp.sort(*.values); # Attempt to print it in order
for %target.kv -> $k,$v {print $k}; # that prints in random order
Run Code Online (Sandbox Code Playgroud)

1-如何%temp按顺序打印哈希?

2-(可选)有没有一种方法可以开始使用哈希变量,而无需my像在 Python 中那样用ie声明它?

3-(可选)我选择了查找方法来解决这个问题,结果代码看起来有点复杂。可以使用任何其他方法缩短解决方案吗?

use*_*601 8

所以有几件事我想看看,但看起来你确实在做一些额外的步骤(在评论中你说你已经尝试了一些不同的事情,所以我想你没有” t 初始做一些额外的)。

你首先给了自己德国数字:

my @numDE = <null eins zwei drei vier fünf sechs sieben acht neun>;
Run Code Online (Sandbox Code Playgroud)

接下来,您希望能够根据德语拼写对事物进行排序。我会尝试使用你所接触的方法,但我会在最后向你展示一种更简单的方法。下一步是有效地缓存它们的排序顺序,并将其存储到变量“numrank”中。建立@numDE.sort.kv,我们得到

my %numrank;
for @numDE.sort.kv -> $k, $v {
    %numrank{$v} = $k;
}
say %numrank;
# {acht => 0, drei => 1, eins => 2, fünf => 3, neun => 4, null => 5, sechs => 6, sieben => 7, vier => 8, zwei => 9}
Run Code Online (Sandbox Code Playgroud)

好吧,还不错。另请注意,虽然 的输出%numrank似乎是有序的,但作为散列,它本质上是无序的。它只是碰巧按字母顺序打印键,我们的键和值在这些行上排序。现在我们只需要使用实际数字作为键,而不是使用德语名称。

my %numrank;
for @numDE.sort.kv -> $k, $v {
    my $id == @numDE.first: $v;
    %numrank{$id} = $k;
}
say %numrank;
Run Code Online (Sandbox Code Playgroud)

哎呀,我们得到了同样的东西。这是因为.first返回实际对象。对于它的索引,我们只附上:k副词:

my %numrank;
for @numDE.sort.kv -> $k, $v {
    my $id == @numDE.first: $v, :k;
    %numrank{$id} = $k;
}
say %numrank;
# {0 => 5, 1 => 2, 2 => 9, 3 => 1, 4 => 8, 5 => 3, 6 => 6, 7 => 7, 8 => 0, 9 => 4}
Run Code Online (Sandbox Code Playgroud)

完美,现在我们可以看到 8 (acht) 的值是 0,因为它是第一个,而 2 (zwei) 的值是 9,因为它是最后一个。请注意,我们也可以在这里使用数组,因为我们的索引是数字(使用@numrank然后执行@numrank[$id] = $k

现在整理一些东西。在您的代码中,您有

%temp{"$_"}= %numrank{"$_"} for "2378".comb; # 2378 sample input
Run Code Online (Sandbox Code Playgroud)

这将创建一个无序散列,其中每个键的名称是一个数字,其值是它的等级。这基本上就是我们在上面第一次尝试制作%numrank. 但是因为%temp是一个散列,如果你有任何两个重复的数字,你会失去额外的:

%temp{"$_"}= %numrank{"$_"} for "222".comb;
# {2 => 9} 
Run Code Online (Sandbox Code Playgroud)

相反,我认为您想创建一个可以允许排序的数组:

my @temp = ($_ => %numrank{"$_"}) for "22378".comb;
# ^^ both 2s are preserved
Run Code Online (Sandbox Code Playgroud)

现在您可以简单地对值进行排序:

say @temp.sort: *.values;
Run Code Online (Sandbox Code Playgroud)

你可以直接循环这个:

for @temp.sort(*.values) {
   print .key;
}
Run Code Online (Sandbox Code Playgroud)

更简单的方法

"2378".comb.sort: { @numDE[$^digit] }
# (8 3 7 2) # acht drei seiben zwei 
Run Code Online (Sandbox Code Playgroud)

在这里,我们根据每个数字的德语文本形式对梳理后的数字进行排序。 @numDE作为数字的名称,并且$^digit是一个包含数字的隐式变量([ ]自动将其强制转换为数字)。如果您计划定期使用它,您实际上可以将块存储在一个变量中,如下所示:

my &sort-de = sub ($digit) { @numDE[$digit] };
"87446229".comb.sort: &sort-de;
# (8 9 6 7 4 4 2 2)
Run Code Online (Sandbox Code Playgroud)

如上所述,如果您想以其他方式对其进行样式设置,您可以直接对此进行 for 循环:

for "87446229".comb.sort(&sort-de) {
   say $_
}
Run Code Online (Sandbox Code Playgroud)