Перебор сложной структуры данных

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

%htest = (
  8569 => {
    4587 => [
           {
            date=> "2011-01-15",
            approved=> 1,
           },
           { 
            date=> "2011-01-12",
            approved=> 1,
           },
           ],
    1254 => [
           {
            date=> "2011-01-12",
            approved=> "",
           },
           { 
            date=> "",
            approved=> 1,
           },
           ],
        },
);

Попытка перебрать эту вещь вызывает у меня сильную головную боль. Я пытаюсь получить доступ к количеству элементов под вторым хэш-значением (4587 и 1254). Число тех элементов, где утверждено ="1", и количество элементов, в которых дата содержит значение.

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

Я получил это далеко...

while (my ($id, $surveyhash) = each %{ $htest{'8569'} } ){
    print "$enumid = $subhash\n";
    print Dumper $subhash."\n";
}

Это дает мне "4587" и "1254", но попытка создать дампер на $subhash просто дает мне....

4587 = ARRAY(0x9a9ffb0)
$VAR1 = 'ARRAY(0x9a9ffb0)
';
1254 = ARRAY(0x9a91788)
$VAR1 = 'ARRAY(0x9a91788)
';

Любая идея, как перебрать это чудовище? Джени

3 ответа

Решение

В вашей структуре есть опечатки, вам нужны запятые между внутренними хешами и круглые скобки (а не фигурная скобка)

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

my $approved = 0, my $date_has_value = 0;
while ( my ($k,$vref) = each %htest ) {
    while ( my ($k,$v) = each %$vref ) { 
        # Now you're inside the inner hash, so there will be 2 iterations
        # with $k 4587 and 1254
        foreach my $item (@$v) {
            # Now each $item is a reference to the innermost hashes
            $approved++ if $item->{approved} == 1;
            $date_has_value++ if $item->{date};
        }
    }
}

Вот довольно явная итерация, которая должна помочь вам начать

my ($num_approved, $num_date) = (0, 0);

# outer hash
while (my ($ka, $va) = each %htest)
{
  # inner hash
  while (my ($kb, $vb) = each %{$va})
  {
    # each hash inside the array
    foreach my $h (@{$vb})
    {
      $num_approved += ${$h}{"approved"} == 1;
      $num_date     += length(${$h}{"date"}) > 0;
    }
  }
}

Подсчет совпадений можно выполнить с помощью "скалярного grep".

my ($approved, $date_has_value) = (0, 0);

for my $v1 (values %htest) {
    for my $v2 (values %$v1) {
        $approved       += scalar grep { $$_{approved} eq '1' } @$v2;
        $date_has_value += scalar grep { $$_{date}     ne ''  } @$v2;
    }
}
Другие вопросы по тегам