Como faço para criar e adicionar hashes anônimos a um Hash conhecido durante a execução do script?
-
10-07-2019 - |
Pergunta
Vou tentar ilustrar isto com um exemplo. Vejamos um exemplo comum de um Hash de hashes:
my %HoH = (
flintstones => {
lead => "fred",
pal => "barney",
},
jetsons => {
lead => "george",
wife => "jane",
"his boy" => "elroy",
},
simpsons => {
lead => "homer",
wife => "marge",
kid => "bart",
},
);
Para os meus propósitos, eu gostaria de ser capaz de adicionar um hashes sem nome, ou anônimos% HOH. Não será necessário (ou ser capaz de) definir estas sub-hash até a execução. Como posso fazer isso com Perl?
Tudo o que eu li (e eu li através Perldocs e Google'd já) parece mostrar exemplos em todas as sub-hahes (por exemplo, "Flintstones", "Jetsons", e "simpsons") são definidos.
O que estou fazendo é tentando construir um Hash pai que conterá sub-hashes com linhas de um arquivo CSV:
%TopHash = (
%Line1 => {
cell01 => $some_value1a;
cell02 => $some_value2a;
cell03 => $some_value3a;
},
%Line2 => {
cell01 => $some_value1b;
cell02 => $some_value2b;
cell03 => $some_value3b;
},
%Line3 => {
cell01 => $some_value1c;
cell02 => $some_value2c;
cell03 => $some_value3c;
},
# etc
# etc
# etc
);
O número de "% Linex" hashes que eu preciso não é conhecido até a execução (porque eles representam o número de linhas em um arquivo CSV que é lido em tempo de execução).
Todas as idéias? Se ainda não estiver claro ... Eu ainda estou tentando envolver minha cabeça em torno de hashes Perl.
Solução
Primeiro você cria o hash a partir da linha atual que você está parsing
my %lineHash = (
cell01 => $some_value1a,
cell02 => $some_value1b,
cell03 => $some_value1c
);
ou criar uma referência a um hash outright
my $lineHashRef = {
cell01 => $some_value2a,
cell02 => $some_value2b,
cell03 => $some_value2c
};
Em seguida, você adicionar ao seu haxixe geral, lembrando que as estruturas perl aninhados apenas conter referências a outras estruturas.
$topHash{line1} = \%lineHash;
$topHash{line2} = $lineHashRef;
Atualização Exemplo dado um laço sobre uma matriz de dados para analisar
my %topHash;
foreach my $i (0 .. $#data) {
my %tempHash;
// stuff here to parse $data[$i] and populate %tempHash
$topHash{"line$i"} = \%tempHash;
}
Outras dicas
Para adicionar um hash anônimo em tempo de execução, atribuí-lo como se fosse um elemento de hash normal:
$HoH{key} = { foo => 42 };
ou
$HoH{key} = $hash_ref;
ou
$HoH{key} = \%hash;
#!/usr/bin/perl
use strict;
my %HoH = (
line01 => {
cell01 => "cell0101",
cell02 => "cell0102",
cell03 => "cell0103"
}
);
$HoH{"line02"} =
{
cell01 => "cell0201",
cell02 => "cell0202",
cell03 => "cell0203"
};
foreach my $hohKey (keys %HoH)
{
my $newHash = $HoH{$hohKey};
print "Line Name: $hohKey\n";
foreach my $key (keys %$newHash)
{
print "\t$key => ", $newHash->{$key}, "\n";
}
}
Toda vez que você criar um novo hash a partir de uma linha de dados, você precisa pensar em uma chave única para armazenar os dados na sua tabela topo hash.
my $line = 1;
my %HoH;
while (<>) {
my ($cell01, $cell02, $cell03, @etc) = split /,/;
my $newHash = { cell01 => $cell01, cell02 => $cell02, ... };
my $key = "line$line";
$HoH{$key} = $newHash;
$line++;
}
Agora keys(%HoH)
retornará uma lista (sem classificação) como "line1","line2","line3",...
.
$HoH{"line5"}
retornaria uma referência aos dados para a 5ª linha do seu arquivo.
%{$HoH{"line7"}}
é uma espécie de sintaxe feio, mas ele retorna uma tabela hash de seus dados
da linha 7.
$HoH{"line14"}{"cell02"}
poderia ser usado para chegar a uma parte específica de dados.