В чем разница между push и unshift в Perl? - PullRequest
6 голосов
/ 19 февраля 2010

Может кто-нибудь объяснить, почему push ведет себя так, как показано ниже?

В основном я пытаюсь напечатать значения массива, заполненного push, а также unshift.

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

со смещением

#!/usr/bin/perl
@names = ("Abhijit","Royal Enfield","Google");
@numbers=();
$number=1;
$i=0;
foreach $name (@names) {
    #print $_ . "\n";
    $number=$number+1;
    #push(@numbers,($number));
    unshift(@numbers,($number));
    print("Array size is :" . @numbers . "\n");
    $i=$i+1;
    print("Individual Elements are:" . @numbers[i] . "\n");
    pop(@numbers);
}

rhv:/var/cl_ip_down>./run.sh
Array size is :1
Individual Elements are:2
Array size is :2
Individual Elements are:3
Array size is :3
Individual Elements are:4

без смещения

#!/usr/bin/perl
@names = ("Abhijit","Royal Enfield","Google");
@numbers=();
$number=1;
$i=0;
foreach $name (@names) {
    #print $_ . "\n";
    $number=$number+1;
    push(@numbers,($number));
    #unshift(@numbers,($number));
    print("Array size is :" . @numbers . "\n");
    $i=$i+1;
    print("Individual Elements are:" . @numbers[i] . "\n");
}

rhv:/var/cl_ip_down>./run.sh
Array size is :1
Individual Elements are:2
Array size is :2
Individual Elements are:2
Array size is :3
Individual Elements are:2

/ без всплывающих окон /

#!/usr/bin/perl
@names = ("Abhijit","Royal Enfield","Google");
@numbers=();
$number=1;
$i=0;
foreach $name (@names) {
    #print $_ . "\n";
    $number=$number+1;
    #push(@numbers,($number));
    unshift(@numbers,($number));
    print("Array size is :" . @numbers . "\n");
    $i=$i+1;
    print("Individual Elements are:" . @numbers[i] . "\n");
    #pop(@numbers);
}

rhv:/var/cl_ip_down>./run.sh
Array size is :1
Individual Elements are:2
Array size is :2
Individual Elements are:3
Array size is :3
Individual Elements are:4

с поп

#!/usr/bin/perl
@names = ("Abhijit","Royal Enfield","Google");
@numbers=();
$number=1;
$i=0;
foreach $name (@names) {
    #print $_ . "\n";
    $number=$number+1;
    #push(@numbers,($number));
    unshift(@numbers,($number));
    print("Array size is :" . @numbers . "\n");
    $i=$i+1;
    print("Individual Elements are:" . @numbers[i] . "\n");
    pop(@numbers);
}

rhv:/var/cl_ip_down>./run.sh
Array size is :1
Individual Elements are:2
Array size is :1
Individual Elements are:3
Array size is :1
Individual Elements are:4

Ответы [ 5 ]

27 голосов
/ 19 февраля 2010

Вы действительно должны использовать use strict; и use warnings; в своем коде. Их активация позволит вам идентифицировать ошибки в вашем коде.

Изменить все экземпляры следующего:

foreach $name (@names) -> for my $i (@names), поскольку вы ничего не делаете с элементами в массиве @names.

@numbers[i] -> $numbers[$i], поскольку именно здесь вы допустили ошибку, используя срез массива вместо ссылки на элемент массива.

Это не C. Перед каждой «переменной» должен быть символ ($, @, %, & и т. Д.). Это i действительно должно быть $i.


Что касается разницы между push и shift, в документации поясняется:

perldoc -f push

push ARRAY, LIST

Обрабатывает ARRAY как стек и помещает значения LIST в end ARRAY. Длина ARRAY увеличивается на длину LIST. ... Возвращает количество элементов в массиве после завершенного "нажатия".

perldoc -f unshift

Массив без смещения, СПИСОК

Делает противоположность сдвигу. Или противоположность толчка, в зависимости от того, как вы на это смотрите. Добавляет список в перед массива и возвращает новое количество элементов в массиве.


Говоря ASCII-математически ...

        +---------+           +-----------+        +---------+ 
<-----  | ITEM(S) |  ----->   | (@) ARRAY | <----- | ITEM(S) | ----->
 shift  +---------+  unshift  +-----------+  push  +---------+   pop
                              ^           ^
                              FRONT       END
13 голосов
/ 19 февраля 2010

unshift используется для добавления значения или значений в начало массива:

Делает противоположность shift. Или противоположность push, в зависимости от того, как вы на это смотрите.

Новые значения становятся первыми элементами в массиве.

push добавляет элементы в end массива:

Обрабатывает ARRAY как стек и помещает значения LIST в конец ARRAY.

7 голосов
/ 19 февраля 2010

Это действительно должен быть комментарий, но он слишком длинный для поля для комментариев, поэтому вот он.

Если вы хотите проиллюстрировать разницу между unshift и push , вам будет достаточно:

#!/usr/bin/perl

use strict; use warnings;

my @x;

push @x, $_ for 1 .. 3;

my @y;

unshift @y, $_ for 1 .. 3;

print "\@x = @x\n\@y = @y\n";

Выход:

@x = 1 2 3
@y = 3 2 1

Примечание use strict; защищает вас от многих ошибок программиста, а use warnings; предупреждает вас при использовании конструкций сомнительного значения. На вашем уровне, ни один не является обязательным.

0 голосов
/ 24 сентября 2017

Я не видел никакой формулировки того, что эти методы на самом деле делают с точки зрения сложности операций, что и помогло мне в концептуализации: в сущности, я считаю, что это называется «сдвигом», потому что на самом деле он должен сдвигать все элементы в вашем массиве с новыми индексами для правильного обновления свойства длины.

push () и pop () используют более простую операционную сложность. Независимо от того, какое число из n значений в вашем массиве или в файле array.length, push или pop всегда будет выполнять 1 операцию. Ему не нужно иметь дело с индексами, ему не нужно итерировать, ему нужно только выполнить одну операцию, всегда в конце стека, либо добавляя, либо удаляя значение и индекс.

Самое главное, обратите внимание при использовании push / pop, что другие элементы в массиве не затрагиваются - они имеют одинаковые значения в тех же индексах вашего массива. Длина массива также автоматически обновляется в соответствии с тем, что вы ожидаете при удалении или добавлении значений.

С другой стороны, shift () и unshift () не только добавляют или удаляют, но и фактически должны «сдвигать» все другие элементы в вашем массиве в разные индексы. Это более сложно и занимает больше времени, потому что количество операций зависит от n, количества элементов в вашем массиве или array.length. Для каждого n + 1, большего, он должен сделать еще 1 операцию, чтобы сдвинуть каждое из значений в правильный индекс, должным образом обновляя длину должным образом.

В противном случае, если бы он не выполнил n операций после shift () и переместил бы другие элементы, у вас не было бы элемента с индексом 0, и это не изменило бы длину вашего массива, не так ли? Мы хотим, чтобы длина наших массивов обновлялась интуитивно, а для сдвига и снятия приходится выполнять больше операций, чтобы выполнить это.

0 голосов
/ 12 сентября 2017

Обратите внимание, что

предварительно выделенный массив сбалансирован по направлению к концу 0 массива (это означает, что в дальнем конце списка больше свободного места, чем есть до элемента 0 списка). Это сделано специально , чтобы толчки были более эффективными, чем unshifts . http://www.perlmonks.org/?node_id=17890

Хотя списки вполне подходят как "Perl умно закодирован, потому что ожидалось использование списков в качестве очередей (там же)" .

Для сравнения, в различных движках JavaScript shift / unshift для массивов выглядит значительно медленнее .

...