我可以 return 多个 Pairs from a map feeding into a hash 吗?
Can I return multiple Pairs from a map feeding into a hash?
我正在尝试创建一个按键或值查找的散列。要查找两种方式,我希望值是键(值是它们的键)。
<
H He
>
==> map( {
state $n = 0; $n++;
$n => $_.Str,
$_.Str => $n
} )
==> my %elements;
%elements.perl.say;
%elements{2}.WHAT.say;
这让我感到奇怪:
{"1\tH H\t2" => $(2 => "He", :He(2))}
(Any)
只要一对就可以了:
<
H He
>
==> map( {
state $n = 0; $n++;
$n => $_.Str
} )
==> my %elements;
%elements.perl.say;
%elements{2}.WHAT.say;
现在我得到了我想要的,但没有反向对:
{"1" => "H", "2" => "He"}
(Str)
您的 map
return 是一系列 List
values that each contain two Pair
值。
将其提供给散列不会自动将其展平,每个 List
成为散列的键或值。
有几种方法可以让它做你想做的事:
使用flat
您可以使用内置的 flat
函数将 map
的结果展平,以便哈希接收 Pair
s:
的序列
<H He>
==> map {
(state $n)++;
+$n => ~$_,
~$_ => +$n
}\
==> flat()
==> my %elements;
%elements.say; # {1 => H, 2 => He, H => 1, He => 2}
%elements{2}.WHAT.say; # (Str)
map
和 flat
return 惰性序列,因此即使元素列表很大,这(理论上)也是内存高效的。
- 旁注: 我还写了
+$n
而不是 $n
因为 =>
对构造运算符(如 ,
List construction operator) 没有 "decontainerize" 它的参数 - 如果你给它一个项目容器,比如 $
变量,它会直接绑定到那个而不是它包含的值,这会导致下一个 $n++
也影响上一次迭代的 Pair
return。给对构造运算符一个值表达式而不是一个变量,可以避免这种情况。
使用slip
slip
是 flat
的由内而外的版本:
<H He>
==> map {
(state $n)++;
slip
+$n => ~$_,
~$_ => +$n
}\
==> my %elements;
map
的每次迭代现在 return 都是一个 Slip
类型的值,这与 List
类似,只是它会自动分解到它变成的任何父列表中一部分。
重构
如果您不受限于您的特定方法,这里有两种可能更清晰的方法来生成相同的散列:
my @keys = 1..*;
my @values = <H He>;
my %elements = flat (@keys Z=> @values), (@values Z=> @keys);
或者:
my %elements = 1..* Z=> <H He>;
push %elements, %elements.invert;
(Z
是 "zip" 元运算符)
我正在尝试创建一个按键或值查找的散列。要查找两种方式,我希望值是键(值是它们的键)。
<
H He
>
==> map( {
state $n = 0; $n++;
$n => $_.Str,
$_.Str => $n
} )
==> my %elements;
%elements.perl.say;
%elements{2}.WHAT.say;
这让我感到奇怪:
{"1\tH H\t2" => $(2 => "He", :He(2))}
(Any)
只要一对就可以了:
<
H He
>
==> map( {
state $n = 0; $n++;
$n => $_.Str
} )
==> my %elements;
%elements.perl.say;
%elements{2}.WHAT.say;
现在我得到了我想要的,但没有反向对:
{"1" => "H", "2" => "He"}
(Str)
您的 map
return 是一系列 List
values that each contain two Pair
值。
将其提供给散列不会自动将其展平,每个 List
成为散列的键或值。
有几种方法可以让它做你想做的事:
使用flat
您可以使用内置的 flat
函数将 map
的结果展平,以便哈希接收 Pair
s:
<H He>
==> map {
(state $n)++;
+$n => ~$_,
~$_ => +$n
}\
==> flat()
==> my %elements;
%elements.say; # {1 => H, 2 => He, H => 1, He => 2}
%elements{2}.WHAT.say; # (Str)
map
和 flat
return 惰性序列,因此即使元素列表很大,这(理论上)也是内存高效的。
- 旁注: 我还写了
+$n
而不是$n
因为=>
对构造运算符(如,
List construction operator) 没有 "decontainerize" 它的参数 - 如果你给它一个项目容器,比如$
变量,它会直接绑定到那个而不是它包含的值,这会导致下一个$n++
也影响上一次迭代的Pair
return。给对构造运算符一个值表达式而不是一个变量,可以避免这种情况。
使用slip
slip
是 flat
的由内而外的版本:
<H He>
==> map {
(state $n)++;
slip
+$n => ~$_,
~$_ => +$n
}\
==> my %elements;
map
的每次迭代现在 return 都是一个 Slip
类型的值,这与 List
类似,只是它会自动分解到它变成的任何父列表中一部分。
重构
如果您不受限于您的特定方法,这里有两种可能更清晰的方法来生成相同的散列:
my @keys = 1..*;
my @values = <H He>;
my %elements = flat (@keys Z=> @values), (@values Z=> @keys);
或者:
my %elements = 1..* Z=> <H He>;
push %elements, %elements.invert;
(Z
是 "zip" 元运算符)