#arrays #perl #hash #reference
Вопрос:
У меня есть файл, который считывается и разделяется на %объектов, %объектов заполняются, как показано ниже.
$VAR1 = 'cars';
$VAR2 = {
'car1' => {
'info1' => '"fast"',
'info2' => 'boring'
},
'car2' => {
'info1' => '"slow"',
'info2' => 'boring info'
},
'car3' => {
'info1' => '"unique"',
'info2' => 'useless info'
}
};
$VAR3 = 'age';
$VAR4 = {
'new' => {
'info3' => 'rust',
'info4' => '"car1"'
},
'old' => {
'info3' => 'shiny',
'info4' => '"car2" "car3"'
}
}
};
Моя цель состоит в том, чтобы вставить такие данные, как «car1 быстрая ржавчина, car2 медленный блеск, car3 уникальный блеск», в базу данных, но я не могу получить, например, «ржавчина соответствует возрасту на основе info4» ..
my $key = cars;
my $key2 = age;
foreach my $obj (keys %{$objects{$key}}) { # for every car
@info1s = $objects{$type}{$obj}{'info1'} =~ m/"(.*?)"/g; # added to clean up all info1
foreach my $infos ($info1s) {
dbh execute insert $obj $infos # this gives me "car1 fast, car2 slow, car3 unique"
}
...
Может ли кто-нибудь, пожалуйста, указать мне правильное направление для получения и хранения информации 4 с соответствующей информацией 1/info2?
Спасибо!
Комментарии:
1. Как это связано-это потому
info4
, что имеет значениеcar1
, которое является ключом во второй хэш-ссылке$VAR2
? Похоже, вам просто нужно тщательно перебрать эти структуры данных. Кстати, пожалуйста, добавьте, какой из показанных дампов является структурой данных в коде. В коде есть только один (%objects
), но дамп показывает несколько.2. Да, именно так они соотносятся, и я изо всех сил пытаюсь понять, как им соответствовать. Пример кода должен давать вывод только из VAR1 и VAR2, поскольку я изо всех сил пытаюсь сопоставить и извлечь данные из остальных. Если я продолжу спускаться по петле (foreach), добавив еще один $obj2 с $key2, я просто получу беспорядок записей, например, каждая машина будет быстрой, медленной и уникальной и т.д..
3. Всегда ли это одни и те же метки,
info1
сквозныеinfo4
, в хэшрефе второго уровня? Или это просто две пары ключ-значение в нижней (самой глубокой) хэшрефе?4. Это всегда одни и те же ярлыки, поэтому ответ принимается. Хороший трюк с данными::Лист::Ходок, чтобы получить самые глубокие значения. Я посмотрю, смогу ли я поиграть с этим, чтобы все это подходило, потрясающе!
Ответ №1:
Я полагаю, что цель состоит в следующем. Получите значения для info4
ключей () в $VAR4
хэш-ссылке самого глубокого уровня и найдите их как ключи верхнего уровня в $VAR2
хэш-ссылке. Затем свяжите с ними обоими значение из info3
ключа (), их «родного брата» в хэшрефе их собственного $VAR4
самого глубокого уровня, а также значение ключа ( info1
) из $VAR2
.
Для этой цели можно обойти структуру вручную, особенно если она всегда имеет те же два уровня, что и показано на рисунке, но с библиотеками это проще и лучше. Я использую Data::Leaf::Walker для получения листьев (самых глубоких значений) и ключевых путей к ним, а Data::Diver-для получения значений для известных путей.
use warnings;
use strict;
use feature 'say';
use Data::Dump;
use Data::Leaf::Walker;
use Data::Diver qw(Dive);
my $hr1 = {
'car1' => { 'info1' => 'fast', 'info2' => 'boring' },
'car2' => { 'info1' => 'slow', 'info2' => 'boring info' },
'car3' => { 'info1' => 'unique', 'info2' => 'useless info' }
};
my $hr2 = {
'new' => { 'info3' => 'rust', 'info4' => 'car1' },
'old' => { 'info3' => 'shiny', 'info4' => 'car2 car3' }
};
my $walker = Data::Leaf::Walker->new($hr2);
my %res;
while ( my ($path, $value) = $walker->each ) {
next if $path->[-1] ne 'info4';
# Some "values" have multiple needed values separated by space
for my $val (split ' ', $value) {
# Get from 'info4' path the one to its sibling, 'info3'
my @sibling_path = ( @{$path}[0..$#$path-1], 'info3' );
# Collect results: values of `info3` and `info1`
push @{$res{$val}},
Dive( $hr2, @sibling_path ),
Dive( $hr1, ($val, 'info1') );
}
}
dd %res;
Это предполагает несколько вещей и требует некоторых сокращений, для простоты.
Во-первых, я использую явные infoN
ключи из вопросов и двухуровневую структуру. Если данные отличаются или могут отличаться, это не должно быть сложно настроить.
Далее, это предполагает, что значение, как car1
всегда, существует в качестве ключа в другой хэшрефе. Добавьте exists
проверку для этого ключа, если возможно, что он не существует в качестве ключа.
Я удалил некоторые дополнительные цитаты из данных. (Если это относится к записи базы данных, сделайте это при построении инструкции. Если данные поступают с такими дополнительными кавычками, должно быть легко настроить код, чтобы учесть их.)
Вышеприведенная программа печатает
{ car1 => ["ржавчина", "быстро"], car2 =>> ["блестящий", "медленный"], car3 =>>> ["блестящий", "уникальный"], }
(Я использую Data::Dump для отображения сложной структуры данных, для ее простоты и компактного вывода по умолчанию.)