Perl 6 在循环列表时显示索引
Perl 6 to show index while looping through a list
当循环列表(或数组)时,有没有办法知道循环内当前元素的索引?
当然可以通过索引循环解决问题:
my @aa = 8 .. 12;
say "$_\t@aa[$_]" for 0 ..^ @aa.elems;
但也许像下面这样的事情是可能的(我用 .CURRENT_INDEX
标记了我正在寻找的方法)?
my @aa = 8 .. 12;
say $_.CURRENT_INDEX\t$_ for @aa;
获取列表循环当前元素的循环索引,可以使用列表的.kv
方法。它 returns 索引和值的交错序列:
my @aa = 8 .. 12;
for @aa.kv -> $i, $_ { say "$i: $_" }
输出:
0: 8
1: 9
2: 10
3: 11
4: 12
TLDR: 使用 .kv
或 .pairs
.
这是幕后真正发生的事情:
my @aa = 8 .. 12;
my \iterator = @aa.iterator;
while ($_ := iterator.pull-one) !=:= IterationEnd {
say $_
}
在这种情况下,iterator
中的值是匿名的 class,扮演 Iterator 角色。
一个Iterator可能有也可能没有任何方法知道它产生了多少值。例如 .roll(*)
的 Iterator 不需要知道到目前为止它产生了多少个值,所以它不需要。
Iterator 可以实现一个 returns 其当前索引的方法。
my @aa = 8 .. 12;
my \iterator = class :: does Iterator {
has $.index = 0; # declares it as public (creates a method)
has @.values;
method pull-one () {
return IterationEnd unless @!values;
++$!index; # this is not needed in most uses of an Iterator
shift @!values;
}
}.new( values => @aa );
say "{iterator.index}\t$_" for Seq.new: iterator;
1 8
2 9
3 10
4 11
5 12
您也可以在更高级别的结构中进行;
my @aa = 8 .. 12;
my $index = 0;
my $seq := gather for @aa { ++$index; take $_ };
say "$index\t$_" for $seq;
要使 $_.CURRENT-INDEX
正常工作,需要包装结果。
class Iterator-Indexer does Iterator {
has Iterator $.iterator is required;
has $!index = 0;
method pull-one () {
my \current-value = $!iterator.pull-one;
# make sure it ends properly
return IterationEnd if current-value =:= IterationEnd;
# element wrapper class
class :: {
has $.CURRENT-INDEX;
has $.value;
# should have a lot more coercion methods to work properly
method Str () { $!value }
}.new( CURRENT-INDEX => $!index++, value => current-value )
}
}
multi sub with-index ( Iterator \iter ){
Seq.new: Iterator-Indexer.new: iterator => iter;
}
multi sub with-index ( Iterable \iter ){
Seq.new: Iterator-Indexer.new: iterator => iter.iterator;
}
my @aa = 8 .. 12;
say "$_.CURRENT-INDEX()\t$_" for with-index @aa.iterator;
# note that $_ is an instance of the anonymous wrapper class
再次使用更高级别的结构:
my @aa = 8 .. 12;
my \sequence := @aa.kv.map: -> $index, $_ {
# note that this doesn't close over the current value in $index
$_ but role { method CURRENT-INDEX () { $index }}
}
say "$_.CURRENT-INDEX()\t$_" for sequence;
我认为如果您想要这样的东西,您应该只使用 .pairs
。 (或使用 .kv
但这基本上需要使用带有两个参数的 for
的块形式)
my @aa = 8 .. 12;
say "$_.key()\t$_.value()" for @aa.pairs;
这是另一种方法,使用您自己的索引变量:
my @aa = 8..12;
say $++, ": $_" for @aa;
输出:
0: 8
1: 9
2: 10
3: 11
4: 12
当循环列表(或数组)时,有没有办法知道循环内当前元素的索引?
当然可以通过索引循环解决问题:
my @aa = 8 .. 12;
say "$_\t@aa[$_]" for 0 ..^ @aa.elems;
但也许像下面这样的事情是可能的(我用 .CURRENT_INDEX
标记了我正在寻找的方法)?
my @aa = 8 .. 12;
say $_.CURRENT_INDEX\t$_ for @aa;
获取列表循环当前元素的循环索引,可以使用列表的.kv
方法。它 returns 索引和值的交错序列:
my @aa = 8 .. 12;
for @aa.kv -> $i, $_ { say "$i: $_" }
输出:
0: 8
1: 9
2: 10
3: 11
4: 12
TLDR: 使用 .kv
或 .pairs
.
这是幕后真正发生的事情:
my @aa = 8 .. 12;
my \iterator = @aa.iterator;
while ($_ := iterator.pull-one) !=:= IterationEnd {
say $_
}
在这种情况下,iterator
中的值是匿名的 class,扮演 Iterator 角色。
一个Iterator可能有也可能没有任何方法知道它产生了多少值。例如 .roll(*)
的 Iterator 不需要知道到目前为止它产生了多少个值,所以它不需要。
Iterator 可以实现一个 returns 其当前索引的方法。
my @aa = 8 .. 12;
my \iterator = class :: does Iterator {
has $.index = 0; # declares it as public (creates a method)
has @.values;
method pull-one () {
return IterationEnd unless @!values;
++$!index; # this is not needed in most uses of an Iterator
shift @!values;
}
}.new( values => @aa );
say "{iterator.index}\t$_" for Seq.new: iterator;
1 8
2 9
3 10
4 11
5 12
您也可以在更高级别的结构中进行;
my @aa = 8 .. 12;
my $index = 0;
my $seq := gather for @aa { ++$index; take $_ };
say "$index\t$_" for $seq;
要使 $_.CURRENT-INDEX
正常工作,需要包装结果。
class Iterator-Indexer does Iterator {
has Iterator $.iterator is required;
has $!index = 0;
method pull-one () {
my \current-value = $!iterator.pull-one;
# make sure it ends properly
return IterationEnd if current-value =:= IterationEnd;
# element wrapper class
class :: {
has $.CURRENT-INDEX;
has $.value;
# should have a lot more coercion methods to work properly
method Str () { $!value }
}.new( CURRENT-INDEX => $!index++, value => current-value )
}
}
multi sub with-index ( Iterator \iter ){
Seq.new: Iterator-Indexer.new: iterator => iter;
}
multi sub with-index ( Iterable \iter ){
Seq.new: Iterator-Indexer.new: iterator => iter.iterator;
}
my @aa = 8 .. 12;
say "$_.CURRENT-INDEX()\t$_" for with-index @aa.iterator;
# note that $_ is an instance of the anonymous wrapper class
再次使用更高级别的结构:
my @aa = 8 .. 12;
my \sequence := @aa.kv.map: -> $index, $_ {
# note that this doesn't close over the current value in $index
$_ but role { method CURRENT-INDEX () { $index }}
}
say "$_.CURRENT-INDEX()\t$_" for sequence;
我认为如果您想要这样的东西,您应该只使用 .pairs
。 (或使用 .kv
但这基本上需要使用带有两个参数的 for
的块形式)
my @aa = 8 .. 12;
say "$_.key()\t$_.value()" for @aa.pairs;
这是另一种方法,使用您自己的索引变量:
my @aa = 8..12;
say $++, ": $_" for @aa;
输出:
0: 8
1: 9
2: 10
3: 11
4: 12