Functional programming 如何从功能上将嵌套哈希转换为记录列表?
假设我有一个描述货币数量的嵌套哈希:Functional programming 如何从功能上将嵌套哈希转换为记录列表?,functional-programming,raku,Functional Programming,Raku,假设我有一个描述货币数量的嵌套哈希: my %money = (coins => {'50c' => 4}, notes => {'10' => 1, '20' => 5}); 我想要的格式是记录列表: my @money = [ (:type('coins'), :subtype('50c'), value => 4), (:type('notes'), :subtype('10'), value => 1), (:type('notes
my %money = (coins => {'50c' => 4}, notes => {'10' => 1, '20' => 5});
我想要的格式是记录列表:
my @money = [
(:type('coins'), :subtype('50c'), value => 4),
(:type('notes'), :subtype('10'), value => 1),
(:type('notes'), :subtype('20'), value => 5),
];
最明显的答案是循环:
my @money;
for %money.kv -> $type, %sub-records {
for %sub-records.kv -> $subtype, $value {
@money.push: (:$type, :$subtype, :$value);
}
}
但是我不喜欢把变量从填充它的代码中分离出来。接下来,我尝试在输入哈希上使用函数转换创建变量:
%money.kv.map: -> $k1, %hsh2 { :type($k1) X, %hsh2.kv.map(->$k2, $v2 {:subtype($k2), :$v2, :value($v2)}) }
但是我没有正确的筑巢。我要一张单子。另外,上面的内容读起来很混乱
折衷方案是聚集
/获取
构造,它允许我通过迭代构造一个列表,在主范围中没有任何临时/未初始化的垃圾:
my @money = gather for %money.kv -> $type, %sub-records {
for %sub-records.kv -> $subtype, $value {
take (:$type, :$subtype, :$value);
}
};
但是我很好奇,用像map
、X
或Z
和flat
这样的列表转换,什么是正确的方法?(“key1”、“key2”和“value”是精细的字段名,因为算法不应该是特定于域的。)
编辑:我应该提到,在Perl 6中,gather
/take
是最具可读性的解决方案(最好用于不只是写的代码)。我仍然对纯功能解决方案感到好奇。my@money=%money.map:
->(:键($type),:值(%records)){
溜
:$type xx*
Z
('subtype'X=>%records.keys)
Z
('value'X=>%records.values)
}
您可以执行.kv.map:->$type,%records{…}
解构Pair对象->(:key($type),:value(%records)){…}
创建一个:$type
对type=>$type
无限重复:$type xx*
(:$type
在其任何输入停止时停止)Z
创建对的列表('subtype'X=>%records.keys)
(请注意,如果不修改调用之间的散列,则
和.keys
的顺序相同).values
将两个列表拉入拉链Z
导致序列的元素滑入外部序列slip
(
会变平太多)flat
如果你想把它们分类的话
my@money=%money.sort.map:#“coins”在“notes”之前排序
->(:键($type),:值(%records)){
#按键的数字部分排序
我的@sorted=%records.sort(+*.key.match(/^\d++/);
溜
:$type xx*
Z
('subtype'X=>@sorted».key)
Z
('value'X=>@sorted».value)
}
你可以做
.sort».kv.map:->($type,%records){…}
我认为这是收集
/获取
@BradGilbert的一个很好的用法,因为它可能是最具可读性的解决方案,但我对纯函数方式很好奇。我正在读你的答案。谢谢!使用无限列表和第一个Z
确实使它更简单。(X
会起作用,但这会创建另一层嵌套,需要用另一张纸片来移除)