这是一个 MRE(显示了两次尝试,保留了调试以提供帮助)尝试在具有系列列的 DataFrame 上使用 AT-POS 进行 2d 下标...
class Series does Positional {
has Real @.data = [0.1,0.2,0.3];
method AT-POS( $p ) {
@!data[$p]
}
}
class DataFrame does Positional {
has Series @.series;
#`[ ATTEMPT #1
method AT-POS( $p, $q? ) {
given $q {
when Int { #say 'Int';
@!series[$p][$q]
}
when Whatever { #say '*';
@!series[$p].data
}
default { #say 'default';
@!series[$p]
}
}
}
#]
# ATTEMPT #2
method AT-POS(|c) is raw { #`[dd c;] @!series.AT-POS(|c) }
}
my $df = DataFrame.new( series => [Series.new xx 3] );
say $df[1].data; #[0.1 0.2 0.3]
say $df[1][2]; #0.3
say $df[0,1]; #(Series.new(data => $[0.1, 0.2, 0.3]) Series.new(data => $[0.1, 0.2, 0.3]))
say $df[1;2]; #0.3
say $df[1;*]; #got (0.1) ... expected [0.1 0.2 0.3]
say $df[*;1]; #got (0.2) ... wanted [0.2 0.2 0.2]
Run Code Online (Sandbox Code Playgroud)
我已经研究过 SO 并发现了三个相关问题here、here和here ...并且我的代码中的尝试#2试图将@lizmats答案应用于第三个问题。令人鼓舞的是,我的 MRE 中的两次尝试都有相同的行为。但我无法锻炼
when Whatever {}没有输入该选项(尝试#1)|c正在做什么 - 尽管我可以看到它在单下标情况下工作(尝试#2)我已经做了一些实验,multi postcircumfix:<[ ]>( DataFrame:D $df, @slicer where Range|List ) is export {}但这似乎使事情变得过于复杂。
=================
@jonathan 提供的很好的答案,基于 @Lizmat 的原始答案 - 谢谢!这是最终的工作代码:
class Series does Positional {
has Real @.data = [0.1,0.2,0.3];
method elems {
@!data.elems
}
method AT-POS( |p ) is raw {
@!data.AT-POS( |p )
}
}
class DataFrame does Positional {
has Series @.series;
method elems {
@!series.elems
}
method AT-POS( |p ) is raw {
@!series.AT-POS( |p )
}
}
my $df = DataFrame.new( series => Series.new xx 3 );
say $df[1].data; #[0.1 0.2 0.3]
say $df[1][2]; #0.3
say $df[0,1]; #(Series.new(data => $[0.1, 0.2, 0.3]) Series.new(data => $[0.1, 0.2, 0.3]))
say $df[1;2]; #0.3
say $df[1;*]; #(0.1 0.2 0.3)
say $df[*;1]; #(0.2 0.2 0.2)
Run Code Online (Sandbox Code Playgroud)
该AT-POS方法仅传递整数数组索引。
处理切片的逻辑(使用*、范围、其他可迭代对象、zen 切片)位于数组索引运算符中,该运算符被实现为postcircumfix:<[ ]>用于单维索引和postcircumfix:<[; ]>多维索引的多分派子例程。这个想法是,想要充当类似数组的类不需要担心重新实现所有切片行为,而且切片行为将在不同的用户定义类型上表现一致。
为了使切片工作,必须实现elems以及AT-POS. 添加:
method elems() { @!data.elems }
Run Code Online (Sandbox Code Playgroud)
是Series并且:
method elems() { @!series.elems }
Run Code Online (Sandbox Code Playgroud)
给出DataFrame您正在寻找的结果。
如果确实想要不同的切片语义,或者可能有一种比标准切片更有效的实现,那么还可以添加multi索引运算符的候选者(记住标记它们is export)。