2015-04-07 2 views
1

Как перенести круговой массив в Perl?Круговой сдвиг массива

Например,

use strict; 
use warnings; 
use Data::Dump; 

my $a = [[1], [3], [2], [4]]; 
my $shift_index = 2; 
circ_shift($a, $shift_index); 
dd $a; 

должен дать выход:

[[2], [4], [1], [3]] 

$shift_index Так это число позиций, чтобы сдвинуть влево.

ответ

6

Для перемещения элементов вкл и выкл, вы используете shift/unshift и push/pop.

use strict; 
use warnings; 
use Data::Dumper; 

my @list = ("one", "two", "three", "four"); 

push (@list, shift @list); 
print Dumper \@list; 

unshift (@list, pop @list); 
print Dumper \@list; 

поэтому ваша функция «сдвиг» будет выглядеть немного как:

sub cycle_list { 
    my ($list_ref, $number_shift) = @_; 
    for (1 .. $number_shift) { 
     push(@$list_ref, shift @$list_ref); 
    } 
} 

cycle_list(\@list, 2); 
print Dumper \@list; 

Передача списка по ссылке позволяет изменять ссылочный список. Вы можете передать кучу значений и вернуть смещенный список из подпапки, если хотите.

+0

Спасибо! Работает отлично :) –

8
my @a = qw(1 2 3 4); 
my $i = 2; 
push(@a, splice(@a, 0, $i)); 
5

Как Денис Ibaev has intimated, circ_shift лучше всего осуществляется с помощью splice, который может pop несколько элементов сразу и не нужен for цикла.

Это будет выглядеть следующим образом

use strict; 
use warnings; 

use Data::Dump; 

my $a = [[1], [3], [2], [4]]; 
my $shift_index = 1; 
circ_shift($a, $shift_index); 

dd $a; 

sub circ_shift { 
    my ($list, $n) = @_; 
    push @$list, splice @$list, 0, $n; 
} 

выход

[[3], [2], [4], [1]] 
2

Если все, что вы хотите, чтобы пройти через элементы массива в повернутом порядке, вам не нужно возиться с push, pop, или splice, даже если либо модифицировать массив на месте, либо создать новый - наиболее интуитивные подходы для большинства из нас.

Вы можете, однако, создать итератор, который будет проходить массив в повернутом порядке путем применения смещения и прикрепив ее с помощью размера массива:

#!/usr/bin/env perl 

use strict; 
use warnings; 

my @x = ('a' .. 'z'); 

for my $d (3, 5, 43) { 
    my $it = rotated_it(\@x, $d); 
    print "@x[ map $it->($_), 1, 3, 5, 7, 11, 13 ]\n"; 
} 

sub rotated_it { 
    my $k = @{ $_[0] }; 
    my $c = $_[1] - 1; 
    sub { ($_[0] + $c) % $k }; 
} 

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

Выход:

d f h j n p 
f h j l p r 
r t v x b d
Смежные вопросы