在 Raku 中将数字重新排列为非英语字母顺序
Rearrange a number into non-English alphabetical order in 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
returns 实际对象。对于它的索引,我们只是附上 :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
回到 其 原始顺序?通过推导第二个 'originating' 索引 @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)
好的,现在我们有了解决问题所需的正确'translation':
> "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
基本上我们将原始值转换为 'originating index' 值、梳理、排序,最后我们 back-translate 将 'originating index' 值转换为原始值。
(“8 3 7 2”是“acht drei seiben zwei”。感谢您的示例@user0721090601!)。
(注意,trim
用于清理一些格式问题)。
HTH.
我正在尝试将数字重新排列为非英语字母顺序。
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
returns 实际对象。对于它的索引,我们只是附上 :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
回到 其 原始顺序?通过推导第二个 'originating' 索引 @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)
好的,现在我们有了解决问题所需的正确'translation':
> "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
基本上我们将原始值转换为 'originating index' 值、梳理、排序,最后我们 back-translate 将 'originating index' 值转换为原始值。
(“8 3 7 2”是“acht drei seiben zwei”。感谢您的示例@user0721090601!)。
(注意,trim
用于清理一些格式问题)。
HTH.