Подтвердить что ты не робот

Есть ли способ захватить фрагмент до конца анонимного массива в Perl?

Так вот, за последние полчаса меня заставляют заводить бонкеров. Есть ли способ для меня захватить срез массива до конца анонимного массива? Я пробовал:

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

и я пробовал: (split(' ',$test_line))[1..-1]

но отягчающе, ни одна из них не работает. Я действительно не хочу иметь дополнительную временную переменную, созданную промежуточным массивом (мне это не нужно). И я действительно не хочу использовать уродливый и нечитаемый один лайнер (нашел несколько из них в Интернете). Неужели нет прямого способа сделать это?

4b9b3361

Ответ 1

Список, который у вас есть в вашем примере, не может быть разрезан с конца. Это связано главным образом с тем, что списки не являются надлежащими структурами данных в 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 ' ' => ...)

Ответ 2

Когда OP сказал slice, я подумал о splice:

@allTheWordsExceptTheFirstTwo = splice @{[split' ', $test_line]}, 2;
@allExceptTheFirstAndLastTwo = splice @{[split' ', $test_line]}, 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

Ответ 4

Я не верю, что вы можете указать индекс для последнего элемента произвольного выражения списка, но как насчет:

split(' ', (split ' ', $test_line, 2)[1])

Кстати, анонимных массивов здесь нет (или в вашем исходном вопросе), только списки.

Ответ 6

если вы открыты для разделения дважды:

my @g =  (split ' ', $test_str)[1..split(' ', $test_str)];

или более правильно (поскольку split возвращает количество найденных полей (на один больше, чем последний индекс поля, поскольку он основан на 0):

my @g =  (split ' ', $test_str)[1..split(' ', $test_str)-1];

к сожалению, они вызывают устаревшее предупреждение под прагмой "предупреждения" и сжимают содержимое @_ (если вы не используете 5.12, тогда вы хороши, в противном случае используйте временную переменную, встроенную подпитку или цикл).