Posso usar o mapa do Perl com uma fatia de array?
Pergunta
Estou apenas tentando encurtar uma linha de código que atribui HTML::Element->as_trimmed_text de uma matriz de HTML::Elements a algumas variáveis - coisas bastante padrão como:
my ($var1, var2) = ($columns[1]->as_trimmed_text, $columns[2]->as_trimmed_text);
..exceto que há mais algumas colunas, então continua por mais algumas linhas.Tive a brilhante ideia de que poderia usar o mapa, mas não estou tendo muita sorte.Eu tentei variações de
map { $_->as_trimmed_text } @columns[1, 3, 5, 7, 9]
mas continuo recebendo Can't call method "as_trimmed_text" sem um pacote ou referência de objeto.
É possível fazer o que estou tentando ou devo apenas manter o que tenho atualmente?
TIA
EDITAR:coluna -> colunas
Solução
Em primeiro lugar, se você não estiver interessado na saída do map, não deverá usá-lo.Map, como grep, sort, etc, é um filtro.Se você não quiser a saída, use foreach.
Mas você está certo, o mapa foi projetado para resolver exatamente esse tipo de problema.Isso fornecerá a saída desejada, embora não use fatias de array.
@trimmed_columns = map { $column[$_]->as_trimmed_text } (1, 3, 5, 7, 9);
A resposta de Robert P explica melhor por que o original não funcionou.
Outras dicas
Encontrei:
Aqui está um pouco de código que emula o que deve acontecer:
use strict;
use warnings;
package Text;
sub new
{
my $class = shift;
my $text = shift;
return bless { TEXT => $text }, $class;
}
sub as_trimmed_text
{
my $self = shift;
my $text = $self->{TEXT};
$text =~ s/^\s*(.*?)\s*$/$1/;
return $text;
}
package main;
my @texts = ( Text->new(' foo '), Text->new(' bar '), Text->new(' baz '));
my @trimmed = map { $_->as_trimmed_text() } @texts[1, 2];
print "Trimmed were: ", join(',', map { "'$_'" } @trimmed);
Isso funciona e funciona bem;Eu recebo:
Trimmed were: 'bar','baz'
Mas se eu substituir o mapa por esta linha:
my @trimmed = map { $_->as_trimmed_text() } @texts[2, 3];
De repente, recebo esta saída:
Can't call method "as_trimmed_text" on an undefined value
Isso ocorre porque '3' está fora do intervalo de valores válidos em @textos, então ele vivifica automaticamente uma nova entrada e a torna undef
.Então, seu mapa faz
undef->as_trimmed_output()
que vomita.Eu verificaria sua fatia da matriz novamente e garantiria que você não estivesse capturando valores fora dos índices reais disponíveis e, exceto isso, verificaria se você está realmente processando membros HTML::Element com isso map
.Um rápido Data::Dumper::Dumper
sobre os valores em @columns
ajudará imensamente.
Por exemplo, se você alterar seu array para conter
my @texts = ( Text->new(' foo '), Text->new(' bar '), ' baz ');
e tento executá-lo, agora recebo o seu erro:
Can't call method "as_trimmed_text" without a package or object reference at map.pl
Portanto, verifique novamente para ter certeza de que o conteúdo do seu array é na verdade todas as instâncias abençoadas da classe cujo método você está tentando chamar.
Seu map
parece certo para mim.Você tem certeza que o segundo deveria dizer @columns
em vez de @column
?Você tem strict
ativado para detectar erros de digitação em nomes de variáveis?
Você está usando outra variável no segundo exemplo @columns
, mas não @column
.Tente usar o seguinte código:
map { $_->as_trimmed_text } @column[1, 3, 5, 7, 9]