Массив хэшей массивов ссылок на массивы - PullRequest
2 голосов
/ 27 декабря 2011

У меня проблема с доступом к данным, описанным в заголовке вопроса.
Структура данных следующая:

my @structure = (
  {
   "Name" => "Test",
   "Param1" => 1,
   "Data1" => \@test1,
   "Data2" => [\@test3],
   "Data3" => [\@test1, \@test2],    
  },
  ...
);

И мне нужно получить доступ к 1-му (# 0) элементу массива @test3.
Я пробовал что-то вроде этого:

my @array   = @{$_->{'Data2'}}[0];
print $array[0];

Но тогда я получаю ссылку на массив (ARRAY(0x239c3c)) вместо требуемого значения. Я чувствую, что есть что-то глобальное, чего я здесь не понимаю.
Не могли бы вы объяснить, как и почему я должен обратиться к требуемому значению?
Большое спасибо.

Ответы [ 3 ]

4 голосов
/ 27 декабря 2011
use strict;
use warnings;

my @test1 = (1,2,3);
my @test2 = (4,5,6);
my @test3 = (7,8,9);

my @structure = (
  {
   "Name" => "Test",
   "Param1" => 1,
   "Data1" => \@test1,
   "Data2" => [\@test3],
   "Data3" => [\@test1, \@test2],
  }
);

print $structure[0] # $structure is an array, you want first element...
  ->{'Data2'}       # ...which is a hash reference, you want value for 'Data2'...
  ->[0]             # ...which is holding an array reference to (one element) array @test3...
  ->[0];            # ...which is an array reference, and you want first element

отпечатки 7.

4 голосов
/ 27 декабря 2011

print $structure[0]{'Data2'}[0][0]; будет работать!

вы просто забудете последний уровень!

$_->{'Data2'} - ссылка на анонимный массив.

@{$_->{'Data2'}}[0] даетпервый элемент анонимного массива, ссылка на другой массив!

Ваш код работал бы, если бы у вас было "Data2" => \@test3, вместо "Data2" => [\@test3],

3 голосов
/ 27 декабря 2011

Вы можете использовать синтаксический сахар ->, чтобы получить нужную ссылку.Это намного чище, чем использование скобок.

И мне нужно получить доступ к 1-му (# 0) элементу массива @ test3

Хорошо, в вашей структуре это 'd be:

my $element = $structure[0]->{Data2}->[0]->[0];

Это эквивалентно, но сложнее для чтения:

my $element = ${${${$structure[0]}{Data2}}[0]}[0];

И, в данном конкретном случае, вы можете исключить синтаксический сахар ->:

my $element = $structure[0]{Data2}[0][0];

Однако я не знаю, облегчает ли это чтение, и есть случаи, когда стандартный способ синтаксического анализа, который может не выполнять то, что вы хотите.Я склонен сжимать все вместе, когда я ссылаюсь на массив массивов, но это все:

my $element = $array[0][3];     #This is okay
my $element = $array[0]->[3];   #Same as above, but with -> syntax

В противном случае я буду использовать синтаксический подсластитель ->.

Вот объяснение синтаксиса:

  • $structure[0] - это ссылка на первый элемент вашего @structure массива.Он содержит ссылку на хеш.
  • $structure[0]->{Data2} является ссылкой на элемент хеша Data2 в первом элементе в вашем массиве @structure.Это ссылка на массив.
  • $structure[0]->{Data2}->[0] - это ссылка на первую ссылку на массив в хэш-элементе Data2 в первом элементе (0) вашего массива @structure.Это ваш массив @test3.
  • $structure[0]->{Data2}->[0]->[0] - первый элемент массива @test3.

Я также рекомендую использовать модуль Data::Dumper при написанииваш код.Это поможет вам увидеть, на какую структуру вы ссылаетесь, и укажет на любые ошибки в уровнях.Например:

use Data::Dumper;

print $structure[0]->{Data2}->[0] . "\n";

Показывает, что это ссылка на другой слой массива.

print "$structure[0]\n";

Показывает, что это ссылка на хеш, где каждый элемент содержит ссылки намассивы массивов.


Всякий раз, когда вы используете эти очень сложные структуры, он кричит об использовании объектно-ориентированного кодирования Perl.Я не на 100% уверен в том, что вы делаете, поэтому я не могу помочь вам с вашими объектами, но очень сложные структуры имеют тенденцию разрушаться и их почти невозможно поддерживать.

Например, теперь мы делаемthis:

use strict;
use warnings;

my $Foo = "bar";
print "Foo = $foo\n";

Это быстро обнаруживает, что я неправильно написал имя моей переменной, выполнив $foo вместо $Foo.Это было большим улучшением по сравнению со старыми версиями Perl, где такой тип проверки ошибок не мог быть выполнен.

Однако, теперь посмотрим на это:

use strict;
use warnings;

my %hash;
$hash{Foo} = "bar";
print "Foo = $hash{foo}\n";

Мы потеряли компиляциюпроверка ошибок.%hash является допустимой переменной, но определяется $hash{Foo}, а не $hash{foo}.В этом случае use strict ничего не делает для вас.

Использование объектно-ориентированного Perl возвращает эту проверку ошибок:

use strict;
use warnings;
use Object::Foo;

my $hash = Object::Foo->new;
$hash->Foo(bar);
print "Foo = " . $hash->foo . "\n";

Упс!Метод должен быть Foo, а не foo.Однако Perl может обнаружить, что метод foo не существует и снова выдаст ошибку при компиляции.

В приведенном выше примере это довольно просто, но вы имеете дело смассив хэшей массивов массивов.Возможность ошибки умножается на 100 с каждым эталонным доступом.И так как вам приходится повторять эти ссылки снова и снова в вашем коде, ошибка может быть обнаружена в десятках разных мест.Даже если вы могли бы сначала закодировать это, а затем прокомментировать всю структуру в вашем коде, вы не сможете сохранить это, когда вернетесь к этому через три месяца.

Взгляните на Учебники Perldoc и пройдитесь по объектам для объектно-ориентированного программирования.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...