массив для хеширования в perl - PullRequest
4 голосов
/ 08 июля 2010

У меня есть список источников, из которого я выбираю случайные предметы и заполняю список адресатов. Элементы в списке имеют определенный формат. Например:

item1{'name'}
item1{'date'}

и т. Д. И многие другие поля.

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

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

Как сделать имя и дату ключом, а весь элемент - значением?

Ответы [ 4 ]

1 голос
/ 08 июля 2010

my% hash;

  1. Вставьте элемент $ V с ключом $ K?

    $ hash {$ K} = $ V

  2. Найти для определенного имени / ключа $ K?

    if (exists $hash{$K}) { 
        print "it is in there with value '$hash{$K}'\n";
    } else { 
        print "it is NOT in there\n" 
    }

Удалить определенное имя / ключ?

удалить $ hash {$ K}

Сделать имя и дату как ключ, а весь элемент как значение?

Простой способ: просто соберите все вместе

set: $hash{ "$name:$date" } = "$name:$date:$field1:$field2"
get: my ($name2,$date2,$field1,$field2) = split ':', $hash{ "$name:$date" }
del: delete $hash{ "$name:$date" }

Более сложный путь: сохранить как хеш в хэше (Google Perl-объект)* набор:

my %temp;
$temp{"name"} = $name;
$temp{"date"} = $date;
$temp{"field1"} = $field1;
$temp{"field2"} = $field2

$hash{"$name:$date"} = \$temp;

получить:

my $find = exists $hash{"$name:$date"} ? $hash{"$name:$date"} : undef;
if (defined find) { # i.e. it was found
    printf "field 1 is %s\n", $find->{"field1"}
} else {
    print "Not found\n";
}

удалить:

delete $hash{"$name:$date"}
0 голосов
/ 08 июля 2010

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

$hash{ $h->{name} }{ $h->{date} } = $h;
# ... OR ...
$hash{ $h->{date} }{ $h->{name} } = $h;

foreach my $name ( sort keys %hash ) { 
    my $name_hash = $hash{$name};
    foreach my $date ( keys %$name_hash ) { 
        print "\$hash{$name}{$date} => " . Dumper( $name_hash->{$date} ) . "\n";
    }
}

Для произвольных уровней может потребоваться функция обхода

sub traverse_hash (&@) { 
    my ( $block, $hash_ref, $path ) = @_;
    $path = [] unless $path;
    my ( @res, @results );
    my $want           = wantarray;
    my $want_something = defined $want;

    foreach my $key ( %$hash_ref ) { 
        my $l_path = [ @$path, $key ];
        my $value  = $hash_ref->{$key};
        if ( ref( $value ) eq 'HASH' ) { 
            @res = traverse_hash( $block, $value, $l_path );
            push @results, @res if $want_something && @res;
        }
        elsif ( $want_something ) {
            @res = $block->( $l_path, $value );
            push @results, @res if @res;
        }
        else { 
            $block->( $path, $value );
        }
    }
    return unless $want_something;
    return $want ? @results : { @results };
}

Так что это то же самое, что и выше:

traverse_hash {
    my ( $key_path, $value ) = @_;
    print( '$hash{' . join( '}{', @$key_path ) . '} => ' . ref Dumper( $value ));
    ();
} \%hash
;
0 голосов
/ 08 июля 2010

Решение Perl


#!/usr/bin/perl -w

use strict;
use Data::Dumper;

   sub main{
      my %hash;
      my @keys = qw(firstname lastname age);                    # hash's keys


                  #  fname    lname    age
                  # --------|--------|-----
      my @arr  = ( [ 'foo1',  'bar1',  '1' ],
                   [ 'foo2',  'bar2',  '2' ],
                   [ 'foo3',  'bar3',  '3' ]
                 );

      # test if array set up correctly
      print "\$arr[1][1]       : $arr[1][1] \n";                # bar2      


      # loads the multidimensional array into the hash
      for my $row (0..$#arr){
         for my $col ( 0..$#{$arr[$row]} ){
            my $itemnum = "item" . ($row+1);                    # using the item# format you used
            $hash{$itemnum}->{$keys[$col]} = $arr[$row][$col];
         }
      }

      # manually add a 4th item
      $hash{item4} = {"firstname", "foo", "lastname", "bar", "age", "35"};



      # How to Retrieve
      # -----------------------

      # single item pull
      print "item1->firstname : $hash{item1}->{firstname} \n";  # foo1
      print "item3->age       : $hash{item3}->{age}       \n";  # 3

      # whole line 1
      {  local $, = " "; 
         print "full line        :" , %{$hash{item2}} , "\n";   # firstname foo2 lastname bar2 age 2 
      } 

      # whole line 2
      foreach my $key (sort keys %{$hash{item2}}){
         print "$key   : $hash{item2}{$key} \n";
      }


      # Clearer description
      #print "Hash:\n", Dumper %hash;
   }

   main();

Это следует использовать в дополнение к принятому ответу.Ваш вопрос был немного неопределенным относительно требования array to hash, возможно, это модель, которую вы ищете?

0 голосов
/ 08 июля 2010

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

Моя лучшая догадка - что-то вроде:

#!/usr/bin/perl

use strict; use warnings;

my @list = (
    q(item1{'name'}),
    q(item1{'date'}),
);

my %lookup;

for my $entry ( @list ) {
    my ($name, $attrib) = $entry =~ /([^{]+){'([^']+)'}/;
    $lookup{ $name }{ $attrib } = $entry;
}

for my $entry ( keys %lookup ) {
    my %entry = %{ $lookup{$entry} };
    print "@entry{keys %entry}\n"
}

use YAML;
print Dump \%lookup;

Выход:

item1{'date'} item1{'name'}
---
item1:
  date: "item1{'date'}"
  name: "item1{'name'}"
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...