【问题标题】:Can I return multiple Pairs from a map feeding into a hash?我可以从一个映射中返回多个 Pairs 并输入一个散列吗?
【发布时间】:2016-09-03 14:06:28
【问题描述】:

我正在尝试创建一个按键或值查找的哈希。要查找两种方式,我希望值是键(值是它们的键)。

<
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( { ++$ =&gt; ~$_ } )&lt;H He&gt; Z=&gt; 1..* 来创建初始的 Pairs 集。

标签: raku feed-operator


【解决方案1】:

您的map 返回一系列List 值,每个值都包含两个Pair 值。
将其提供给散列不会自动将其展平,每个List 都会成为散列的键或值。

有几种方法可以让它做你想做的事:

使用flat

可以使用内置的flat函数对map的结果进行展平,这样hash就接收到Pairs的序列:

<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)

mapflat 都返回惰性序列,因此即使元素列表很大,这(理论上)也能节省内存。

  • 旁注:我还写了+$n 而不是$n,因为=&gt; 对构造运算符(如, 列表构造运算符)不会“去容器化”它的参数 -如果您给它一个项目容器,例如 $ 变量,它将直接绑定到该容器而不是其中包含的值,这会导致下一个 $n++ 也影响从上一次迭代返回的 Pair。为对构造运算符提供值表达式而不是变量,可以避免这种情况。

使用slip

slipflat 的由内而外的版本:

<H He>
==> map {
    (state $n)++;
    slip
        +$n => ~$_,
        ~$_ => +$n
}\
==> my %elements;

map 的每次迭代现在都返回一个 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”元操作符)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-12-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-10-03
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多