Привязать значения хэша к элементам итеративного массива массивов - PullRequest
1 голос
/ 08 ноября 2011

В perl DBI вы можете привязать значение элемента хеша к определенному столбцу результатов вашего запроса.
Таким образом,
при извлечении каждой строки значение элемента хеша обновляется до текущей строки.

Я пытаюсь выяснить, есть ли способ сделать это в core perl ,
, используя хэш (массив массивов) .

Конечная цель состоит в том, чтобы иметь возможность выполнить что-то вроде этого:

my $i;
my @a = (
  [1,2,3],
  [4,5,6],
  [7,8,9]
);
my %superhash{'first', 'second', 'third'} = (\$i[0], \$i[1], \$i[2]);
for $i (@a) {
  print ${$hash{'first'}} . "\n";
}

Мне бы хотелось иметь возможность указать $hash{'first'} на первый элемент в arrayref,без необходимости иметь массив для предварительного указания.

Ожидаемый результат:

1
4
7

Конечно, этот код не работает, потому что нет элементов, на которые $i ссылаетсятаким образом, они не определены.

Ответы [ 3 ]

3 голосов
/ 08 ноября 2011

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

my @a = (
    [1,2,3],
    [4,5,6],
    [7,8,9]
);

{package Tie::Rows;
    my %keys = qw(first 0 second 1 third 2);
    sub TIEHASH {bless [$_[1]]}               # store glob reference
    sub FETCH {$${$_[0][0]}[$keys{$_[1]}]}    # deref glob as array, lookup key
}

tie my %hash, 'Tie::Rows', *i;  # passing the glob here

for our $i (@a) {  # since the for loop aliases at that level
    print $hash{first} . "\n";
}

который печатает

1
4
7

Вы также можете использовать динамическую область для решения этой проблемы:

sub first  () {$$_[0]}  # each of these uses the array in $_
sub second () {$$_[1]}
sub third  () {$$_[2]}

for (@a) {              # for loop puts each array into $_
    print second, $/;
}

который печатает

2
5
8
0 голосов
/ 08 ноября 2011

Если ваши данные не огромны, вероятно, лучше просто скопировать каждую строку в хеш, например,

 for my $i (@a) {
  my %data;
  @data{qw/first second third/} = @$i;
  print $data{first}, "\n";
}
0 голосов
/ 08 ноября 2011

Вы могли бы что-то придумать с tie, то есть можно сделать код, подобный следующему:

for my $i (@a) {
    tie %hash, 'FirstSecondThird', $i;
    print $hash{first}, "\n";
}

Магия заключается в определении пакета FirstSecondThird (обратите внимание, это не оптимизировано):

package FirstSecondThird;

sub TIEHASH {
  my $class = shift;
  my $self = bless { array => shift,
                     keys => { first => 0, second => 1, third => 2 } }, $class;
  $self;
}

sub FETCH {
  my ($self, $key) = @_;
  my $i = $self->{keys}->{$key};
  $self->{array}->[$i];
}

1;

package main;

my @a = ( [1,2,3], [4,5,6], [7,8,9] );

for my $i (@a) {
  tie %hash, 'FirstSecondThird', $i;
  print $hash{first}+$hash{third}, "\n";
}

Урожайность:

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