Как сравнить два хэша разных уровней в Perl без использования подпрограмм или модулей? - PullRequest
0 голосов
/ 06 июня 2018

мои массивы

my @arr = ('mars','earth','jupiter');
my @arr1 = ('mercury','mars');
my @arr2 = ('planet','earth','star','sun','planet2','mars');
%space = ( 'earth'=>{
              'planet'=> {
                     '1' =>'US',
                     '2' =>'UK'
                    },
              'planet2'=>{
                      '1' =>'AFRICA',
                      '2' =>'AUS'
                   }
               },
        'sun'=>{
               'star' =>{
                       '1' =>'US',
                       '2' =>'UK'
                     }
             },
        'mars' =>{
                 'planet2' =>{
                               '1' =>'US',
                       '2' =>'UK'
                     }
             }

       );

Теперь я сравниваю первые два массива следующим образом

foreach (@arr)
{
  $arr_hash{$_} =1;
}
foreach my $name (keys %space)
{
  foreach my $key (keys %{$space{$name}})
  if ($arr_hash{$name} !=1)
  {
    #do something
  }

Теперь, как мне сравнить третий массив?Я пытаюсь что-то вроде этого

  else
  {
     if($arr2_hash{$key}{$name} !=1)
     {
       #do something else
     }

Я хочу проверить, присутствует ли пара планета + земля (например, комбинация key1 и key2 с первым и вторым элементом в @ arr2) в%пространство тоже?любая помощь?

1 Ответ

0 голосов
/ 06 июня 2018

Я сделал это дважды в Perl.Один раз для Test :: More's is_deeply () и еще раз для perl5i's are_equal () .Делать это правильно не просто.Делать это без подпрограмм просто глупо.Если вы хотите увидеть, как это делается, посмотрите на are_equal(), хотя это можно сделать лучше.


Но я не думаю, что вам на самом деле нужно сравнивать два хэша.

Я думаю, что происходит, вы должны проверить, присутствуют ли вещи в различных массивах в %space.Например ...

my @arr = ('mars','earth','jupiter');

Это будет true, true и false.

my @arr1 = ('mercury','mars');

False, true.

my @arr2 = ('planet','earth','star','sun','planet2','mars');

Предполагается, что это парывсе они верны.

Я собираюсь использовать лучшие имена переменных, чем @arr, которые описывают содержимое, а не тип структуры.Я также собираюсь предположить, что use strict; use warnings; use v5.10; присутствует.

Первые два просты, перебрать массив и проверить, есть ли запись в %space.И мы можем сделать оба массива за один цикл.

for my $name in (@names1, @names2) {
    print "$name...";
    say $space{$name} ? "Yes" : "No";
}

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

my %object_types = (
    earth => "planet", sun => "star", mars => "planet2"
);

Тогда это легко.Убедитесь, что $space{$name}{$type} истинно.

for my $name (keys %object_types) {
    my $type = $object_types{$name};

    print "$name / $type...";
    say $space{$name}{$type} ? "Yes" : "No";
}

Или, если вы застряли с массивом, мы можем перебрать список попарно.

# $i will be 0, 2, 4, etc...
for( my $i = 0; $i < $#stellar_objects; $i+=2 ) {
    my($type, $name) = ($stellar_objects[$i], $stellar_objects[$i+1]);

    print "$name / $type...";
    say $space{$name}{$type} ? "Yes" : "No";
}

Что если у вас есть хештипов с несколькими именами для проверки вместо этого?

my %object_types = (
    planet =>['earth'],
    star =>['sun'],
    planet2 =>['earth','mars']
);

Та же идея, но нам нужен внутренний цикл над массивом имен.Правильное использование имен переменных множественного числа помогает не усложнять ситуацию.

for my $type (keys %object_types) {
    my $names = $object_types{$type};

    for my $name (@$names) {
        print "$name / $type...";
        say $space{$name}{$type} ? "Yes" : "No";
    }
}

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

my @searches = (
    [ planet => 'earth' ],
    [ star => 'sun' ],
    [ planet2 => 'earth' ],
    [ planet2 => 'mars' ],
);

for my $search (@searches) {
    my($type, $name) = @$search;
    print "$name / $type...";
    say $space{$name}{$type} ? "Yes" : "No";
}

Для записи, %space плохо спроектирован.Первые два уровня хороши, имя и тип, это странные хеши, которые неудобны.

'sun'=>{
    'star' =>{
        # This part
        '1' =>'US',
        '2' =>'UK'
    }
},

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

sun => {
    star => [ 'US', 'UK' ]
},

Тогда вы можете получить список стран: $countries = $space{$name}{$type}

Если вы хотите быстрый поиск ключаи порядок не имеет значения, используйте хеш с ключами, являющимися сохраненной вещью, и значением, равным 1 (просто заполнитель для «true»).

sun => {
    star => { 'US' => 1, 'UK' => 1 }
},

Это использует преимущества поиска ключа хеша ипозволяет $space{$name}{$type}{$country} быстро проверить наличие.«Значения» (даже если они хранятся в виде ключей) также гарантированно будут уникальными.Это формально известно как set , набор уникальных значений.

И вы можете хранить дополнительную информацию в значении.

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