Como faço para encolher uma matriz em Perl?
Pergunta
Como posso fazer uma série mais curta em Perl? Eu li algumas páginas indicando que eu posso atribuir:
$#ARRAY = 42;
Eu li que o uso de $ # é obsoleto. Eu preciso de uma solução que irá trabalhar para uma matriz de matrizes, também. Este não fez trabalho:
$#$ARRAY[$i] = 42;
Solução
Eu não estou ciente de atribuir estar $#ARRAY
obsoleta; perldoc perldata
de 5.10.0 certamente não diz nada sobre isso. É a maneira mais rápida para truncar uma matriz.
Se você quer algo um pouco mais legível, o uso splice
:
splice @ARRAY, 43;
. (Nota 43
vez de 42
- $#ARRAY
você recebe o último índice da matriz, enquanto que taks splice
o comprimento da matriz em vez)
Como para trabalhar em arrays de arrays, presumo que significa ser capaz de truncar uma matriz aninhada através de uma referência? Nesse caso, você quer:
$#{$ARRAY->[7]} = 42;
ou
splice @{$ARRAY->[7]}, 43;
Outras dicas
As suas opções são praticamente ilimitado (eu esbocei cinco abordagens aqui), mas sua estratégia será ditada pela exatamente o que suas necessidades e objetivos específicos são. (Todos os exemplos irá converter @array ter não mais do que $ N elementos)
[EDIT]
Como já foi salientado, a forma sugerida na pergunta original não é realmente obsoleto, e fornece o, mas não necessariamente a solução mais legível tersest mais rápido.
$#array = $N-1;
código mínimo:
#best for trimming down large arrays into small arrays
@array = $array[0..($N-1)];
A maioria eficiente para aparar um número pequeno fora de uma grande variedade:
#This is a little less expensive and clearer
splice(@array, $n, @#array);
indesejáveis ??Em quase todos os casos, a menos que você realmente ama delete ():
#this is the worst solution yet because it requires resizing after the delete
while($N-1 < $#array)
{
delete(array[$i]);
}
É útil se você precisa do restante da lista em ordem inversa:
#this is better than deleting because there is no resize
while($N-1 < $#array)
{
pop @array;
#or, "push $array2, pop @array;" for the reverse order remainder
}
útil para economizar tempo no longo prazo:
#don't put more values into the array than you actually want
O $#
variável é obsoleta, mas o recurso $#array
não é.
Para usar a sintaxe $#array
em uma expressão arbitrária que produz uma matriz de referência, fazer $#{ EXPR }
.
Veja a inestimável: http://perlmonks.org/?node=References+quick + referência
Você essencialmente deu a resposta canônica si mesmo. Você encurtar um array definindo o último índice:
$#Array = 42
A $ # notação Foo para denotar o último índice na matriz é absolutamente não obsoleta. Da mesma forma, atribuindo a ele não será obsoleta qualquer um. Citando a documentação perldata:
O comprimento de uma matriz é um valor escalar. Você pode encontrar o comprimento @days matriz de avaliação de $ # dias , como em csh. No entanto, este não é o comprimento da matriz; é o índice do último elemento, que é um valor diferente uma vez que existe normalmente um elemento 0. Atribuir a $ # Dias realmente muda o comprimento da matriz. Encurtar um array Desta forma destrói intervir valores. Alongar uma matriz que estava anteriormente encurtada não recupera valores que estavam naqueles elementos. (É usado para fazê-lo em Perl 4, mas nós tivemos que quebrar isso com certificar-se de destruidores foram chamados quando o esperado.)
- $ # array é o último índice da matriz.
- $ # $ array seria o último índice de um array apontou em US $ array.
- $ # $ array [$ i] significa que você está tentando índice de um escalar - não pode ser feito. $ # {$ Array [3]} resolve adequadamente o subscripting da matriz principal antes de tentar fazer referência o último índice.
-
Usado sozinho
$ # {$ array [3]} = 9;
atribui um comprimento de 9 para o autovivified matriz a matriz $ [3].
-
Em caso de dúvida, use Data :: Dumper:
use Data::Dumper; $#{$array[3]} = 5; $#array = 10; print Dumper( \@array, $array ), "\n";
$ # {$ array [$ i]} = 42;
Você poderia fazer
splice @array, $length;
#or
splice @{$arrays[$i]}, $length;
Existem duas formas de interpretar a questão.
- Como reduzir o comprimento da matriz?
- Como reduzir a quantidade de memória consumida pela matriz?
A maioria das respostas até agora concentrar-se na primeira. Em minha opinião, a melhor resposta para isso é o função emenda. Por exemplo, para remover elementos 10 a partir da extremidade:
splice @array, -10;
No entanto, por causa de como Perl gerencia a memória para arrays, a única maneira de garantir que um conjunto leva menos memória é copiá-lo para um novo array (e deixar a memória da matriz velho ser recuperado). Para isso, eu tenderia a pensar em usar um fatia operação. Por exemplo, para remover 10 elementos:
@new = @old[ 0 .. $#old - 10 ]
Aqui está uma comparação de diferentes abordagens para uma matriz de 500 elementos (usando 2104 bytes):
original: length 500 => size 2104
pound: length 490 => size 2208
splice: length 490 => size 2104
delete: length 490 => size 2104
slice: length 490 => size 2064
Você pode ver que apenas a operação fatia (copiado para uma nova matriz) tem uma menor tamanho do que o original.
Aqui está o código que usei para esta análise:
use strict;
use warnings;
use 5.010;
use Devel::Size qw/size/;
my @original = (1 .. 500);
show( 'original', \@original );
my @pound = @original;
$#pound = $#pound - 10;
show( 'pound', \@pound );
my @splice = @original;
splice(@splice,-10);
show( 'splice', \@splice);
my @delete = @original;
delete @delete[ -10 .. -1 ];
show( 'delete', \@delete );
my @slice = @original[0 .. $#original - 10];
show( 'slice', \@slice);
sub show {
my ($name, $ref) = @_;
printf( "%10s: length %4d => size %d\n", $name, scalar @$ref, size($ref));
}