有没有办法在Perl中获取一个匿名数组末尾的切片?

时间:2010-11-01 21:48:46

标签: perl

所以这让我在过去的半小时里疯狂了。有没有办法让我在一个匿名数组的末尾抓取一个数组切片?我试过了:

(split(' ',$test_line))[1..$#_]

我试过了: (split(' ',$test_line))[1..-1]

但是,这些工作都没有加剧。我真的不希望有一个额外的临时变量实例化到中间数组(我不需要)。我真的不想使用丑陋且难以理解的一个班轮(在网上找到一些)。真的没有直接的方法吗?

6 个答案:

答案 0 :(得分:15)

列表是您示例中的内容,无法从最后切片。这主要是因为列表不是Perl中的正确数据结构,而是解释器用于移动数据的更多构造。因此,知道您只能从开头切片列表,您的选择是将其放入数组变量然后切片,更改算法以返回您想要的内容,或者以下内容:

如果您要将此值分配给某个内容,则可以在不需要的每个插槽中使用undef

 my (undef, @list) = split ' ' => $test_line;

如果您发布更多代码,我可以修改。

或者,您可以使用函数式编程中的一些工具。函数droptake对于在没有其他变量的情况下调整列表大小非常有用:

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,然后你很好,否则请使用临时变量,内联子或循环)。