Почему я не могу написать @F [1 ..- 1], чтобы получить элементы 1..last? - PullRequest
4 голосов
/ 19 июля 2009

В Perl индекс массива -1 означает последний элемент:

@F=(1,2,3);
print $F[-1]; # result: 3

Вы также можете использовать обозначение $#, здесь $#F:

@F=(1,2,3);
print $F[$#F]; # result: 3

Так почему бы -1 и $#F не дать одинаковый результат, когда я хочу указать последний элемент в диапазоне:

print @F[1..$#F]; # 23
print @F[1..-1];  # <empty>

Массив @F[1..-1] должен действительно содержать все элементы от элемента 1 до последнего, не так ли?

Ответы [ 6 ]

19 голосов
/ 19 июля 2009

Ваша проблема в том, что синтаксис @a[b..c] включает в себя две различные операции. Сначала b..c оценивается, возвращая список, а затем @a[] оценивается с этим списком. Оператор диапазона .. не знает, что он используется для подписок на массивы, поэтому, насколько он обеспокоен, нет ничего между 1 и -1. Он возвращает пустой список, поэтому массив возвращает пустой срез.

8 голосов
/ 19 июля 2009

Нет ничего особенного в .. в срезе массива; он просто генерирует запрошенный диапазон, а затем просматривается фрагмент этого диапазона.

То есть @a[-3..-1] => @a[-3,-2,-1] и @a[1..3] => @a[1,2,3], но @a[1..-1] становится @a[()].

5 голосов
/ 19 июля 2009
print join ', ', 1..$#F; # 1, 2, 3, 4, 5, 6, ...
print join ', ', 1..-1;  #

Причина этого в том, что оператор '..' не делает ничего особенного внутри индекса массива.

В контексте списка возвращает список значений, начиная с левого значения до правого значения. Если левое значение больше правого, возвращается пустой список.

<Ч />

$#F - это индекс последнего элемента, который равен длине минус один '@F -1'. (Если длина хотя бы одного.)

$F[-1] - это особый случай, облегчающий доступ к элементам с другого конца, без необходимости расчета позиции вручную.

$F[-1] === $F[ @F -1 ] === $F[ $#F ]

@F[ 1 .. (@F -1) ] === @F[ 1 .. $#F ]

@F[ 1 .. (@F -2) ] === @F[ 1 .. ( $#F -1 ) ]

Зная это, вы можете использовать переменные в операторе диапазона:

use strict;
use warnings;
use feature 'say';

sub list{
  my($arr,$first,$last) = @_;

  $first = @$arr + $first if $first < 0;
  $last  = @$arr + $last  if $last  < 0;

  return @$arr[ $first .. $last ];
}

my @F = 1..3;

say join ', ', list(\@F,1,-1)
2, 3

Примечание: это неполный пример, он не будет работать правильно для некоторых крайних случаев

4 голосов
/ 19 июля 2009

$ # F - последний действительный индекс F, а не количество элементов.

@ F = (1,2,3); # так что $ # F равно 2

2 голосов
/ 20 июля 2009

Правила:

  • если индекс массива неотрицательный (или, что эквивалентно, больше $[), начните отсчет с начала массива
  • если оно отрицательное, отсчет начинается с конца
  • если задан диапазон, вернуть срез массива

Теперь, так же как набор (a, b) пуст, если a> b , набор 1 .. -1 также пуст. Следовательно,

@a[ empty set ]

соответствует пустому фрагменту массива.

0 голосов
/ 19 июля 2009

Оператор [] будет принимать либо один индекс, либо диапазон.

-1 принимается в качестве индекса для обозначения индекса последнего элемента.Правильный путь - $ # F.

Диапазон 1 ..- 1 пуст, и поэтому он ничего не возвращает, потому что оценка диапазона отделена от оценки индекса.

...