所以这让我在过去的半小时里疯狂了。有没有办法让我在一个匿名数组的末尾抓取一个数组切片?我试过了:
(split(' ',$test_line))[1..$#_]
我试过了:
(split(' ',$test_line))[1..-1]
但是,这些工作都没有加剧。我真的不希望有一个额外的临时变量实例化到中间数组(我不需要)。我真的不想使用丑陋且难以理解的一个班轮(在网上找到一些)。真的没有直接的方法吗?
答案 0 :(得分:15)
列表是您示例中的内容,无法从最后切片。这主要是因为列表不是Perl中的正确数据结构,而是解释器用于移动数据的更多构造。因此,知道您只能从开头切片列表,您的选择是将其放入数组变量然后切片,更改算法以返回您想要的内容,或者以下内容:
如果您要将此值分配给某个内容,则可以在不需要的每个插槽中使用undef
:
my (undef, @list) = split ' ' => $test_line;
如果您发布更多代码,我可以修改。
或者,您可以使用函数式编程中的一些工具。函数drop
和take
对于在没有其他变量的情况下调整列表大小非常有用:
sub take {
my $n = shift;
@_[0..$n-1]
}
sub drop {
my $n = shift;
@_[$n..$#_]
}
然后你的例子变成
drop 1, split ' ' => $test_line;
drop 1
通常也称为tail
sub tail {drop 1, @_}
当然,由于所有这些都很短,如果你想内联它:
sub {shift; @_}->(split ' ' => ...)
答案 1 :(得分:6)
当OP说 slice 时,我想到了splice
:
@allTheWordsExceptTheFirstTwo = splice @{[split' ', $test_line]}, 2;
@allExceptTheFirstAndLastTwo = splice @{[split' ', $test_line]}, 2, -2;
答案 2 :(得分:3)
您可以在数组下标中使用负范围来从末尾处理任意数量的元素:
my $x = join ' ' => 'a' .. 'z';
my @x = (split ' ', $x)[-13 .. -1];
但是,这需要您知道split
结果中元素的总数,以消除第一个元素。
如果只在一个地方发生这种情况,那么使用do
块应该有效:
my $x = join ' ', 'a' .. 'z';
my @x = do { my @y = (split ' ', $x); @y[1 .. $#y] };
在你的情况下,如果它应该被频繁使用,我会将整个操作分解为子程序,将字符串而不是split
的结果传递给子程序(可以通过允许进一步推广)用户也可以传递分割模式:
my $x = join ' ', 'a' .. 'g';
my @x = skip_first_n_from_split(3, $x);
print Dump \@x;
sub skip_first_n_from_split {
my ($n, $x) = @_;
my @y = split ' ', $x;
return @y[$n .. $#y];
}
玩得开心:
#!/usr/bin/perl
use strict; use warnings;
my $x = join ' ', 1 .. 8;
my @skippers = map make_skipper(' ', $_), 0 .. 7;
print "@$_\n" for map $_->($x), @skippers;
sub make_skipper {
my ($pattern, $n) = @_;
return sub {
my $string = shift;
my $i = 0;
return [ grep $i++ >= $n, split $pattern, $string ];
}
}
输出:
1 2 3 4 5 6 7 8 2 3 4 5 6 7 8 3 4 5 6 7 8 4 5 6 7 8 5 6 7 8 6 7 8 7 8 8
答案 3 :(得分:2)
我不相信你可以为任意列表表达式的最后一个元素指定索引,但是如何:
split(' ', (split ' ', $test_line, 2)[1])
顺便说一句,这里没有匿名数组(或原始问题),只有列表。
答案 4 :(得分:2)
这只是通过BrowserUK在Perlmonks上整齐地得到answered,这就是你要做的:
my @slice = sub{ @_[1..$#_] }->( split ' ', $test_line );
答案 5 :(得分:0)
如果你愿意分裂两次:
my @g = (split ' ', $test_str)[1..split(' ', $test_str)];
或更正确(因为split返回找到的字段数(比最后一个字段的索引多一个,因为它是从0开始):
my @g = (split ' ', $test_str)[1..split(' ', $test_str)-1];
不幸的是,这些在“warnings”编译指示下抛出了一个弃用的警告,并且删除了@_的内容(除非你使用的是5.12,然后你很好,否则请使用临时变量,内联子或循环)。