在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

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

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

3-(可选)我选择了查找方法来解决此问题,并且所得到的代码看起来有些费解。可以使用其他方法缩短解决方案的时间吗?

解决方法

因此,我要看几件事,但看起来您确实在做一些额外的步骤(在评论中您说过您尝试了一些不同的事情,所以我想您最初并没有做很多额外的操作。

您首先给自己输入了德国数字:

my @numDE = <null eins zwei drei vier fünf sechs sieben acht neun>;

接下来,您希望能够根据德语拼写对事物进行排序。我将尝试使用您所采用的方法,但最后我将向您展示一种更简单的方法。下一步是有效地缓存它们的排序顺序,并将其存储到变量“ 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}

好的,还不错。另请注意,尽管%numrank的输出看起来像是有序的,但作为哈希值,它本质上是无序的。通常,按字母顺序 print 键会出现,并且我们的键和值在这些行上进行排序。现在,我们只需要使用 actual 数字作为键,而不是德语名称。

my %numrank;
for @numDE.sort.kv -> $k,$v {
    my $id == @numDE.first: $v;
    %numrank{$id} = $k;
}
say %numrank;

糟糕,我们得到了同样的东西。这是因为.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}

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

现在可以对一些东西进行排序。在您的代码中,您拥有

%temp{"$_"}= %numrank{"$_"} for "2378".comb; # 2378 sample input

这将创建一个无序哈希,其中每个键的名称是一个数字,其值是其等级。这基本上就是我们上面第一次尝试制作%numrank的过程。但是由于%temp是一个散列,所以如果您重复的任何两位数字都将丢失额外的内容:

%temp{"$_"}= %numrank{"$_"} for "222".comb;
# {2 => 9} 

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

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

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

say @temp.sort: *.values;

您可以直接在此循环:

for @temp.sort(*.values) {
   print .key;
}

更简单的方法

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

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

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

并且如上所述,如果您想以其他方式设置样式,则可以直接在其上执行for循环:

for "87446229".comb.sort(&sort-de) {
   say $_
}
,

考虑此问题的一种方法是翻译问题:我们需要将一种订购惯例转换为另一种订购惯例。

首先设置一对索引中的第一个索引,该索引允许按字母顺序对德语数字元素进行排序(在Raku REPL中执行的代码段):

> my @a = @numDE
[null eins zwei drei vier fünf sechs sieben acht neun]
> my @b = @a.pairs.sort(*.values)>>.keys.flat;
[8 3 1 5 9 0 6 7 4 2]
> say @a[@b]
(acht drei eins fünf neun null sechs sieben vier zwei)

上面,我们显示了可以按索引@b重新排序。但是如何使@b返回到原始顺序?通过导出第二个“原始”索引@c

> my @c = @b.pairs.sort(*.values)>>.keys.flat;
[5 2 9 1 8 3 6 7 0 4]
> say @b[@c]
(0 1 2 3 4 5 6 7 8 9)

好的,现在我们有了解决问题所需的正确“翻译”:

> "2378".comb.trans( 0..9 => @c ).comb.sort.trans( @c => 0..9 ).trim.say
8 3 7 2

编辑-下面的第二个示例:

> "87446229".comb.trans( 0..9 => @c ).comb.sort.trans( @c => 0..9 ).trim.say
8 9 6 7 4 4 2 2

基本上,我们将原始值转换为“原始索引”值,进行梳理,排序,然后最后将“原始索引”值反向转换为原始值。

(“ 8 3 7 2”是“ acht drei seiben zwei”。感谢您的示例@ user0721090601!)。
(请注意,trim用于清除某些格式问题)。

HTH。

相关问答

错误1:Request method ‘DELETE‘ not supported 错误还原:...
错误1:启动docker镜像时报错:Error response from daemon:...
错误1:private field ‘xxx‘ is never assigned 按Alt...
报错如下,通过源不能下载,最后警告pip需升级版本 Requirem...