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;
Foi útil?

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. Ele também tem o efeito colateral de expandir uma matriz de menos de $ N elementos com elementos vazios :

$#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));
}
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top