如何使用foreach循环在两个哈希数组之间进行比较

时间:2018-10-25 03:51:06

标签: perl

我需要使用foreach循环在两个哈希数组之间进行比较。但是我真的不知道该怎么做。

我的原始数据:

NewData(file 1)
Puma
77777 33333 44444 55555 
Adidas
99999 88888 55555 77777 
22222 11111 33333 44444
Brooks
11111 22222 33333 44444 
33333 44444 55555 66666 

OldData(file 2)

Puma
77777 33333 44444 55555 
Adidas
11111 11111 33333 44444 
99999 88888 55555 77777 
Brooks
11111 22222 33333 44444 
33333 44444 55555 66666 

我的hash1:

'Adidas' => {
                        'y1' => [
                                  '88888',
                                  '11111'
                                ],
                        'x2' => [
                                  '55555',
                                  '33333'
                                ],
                        'y2' => [
                                  '77777',
                                  '44444'
                                ],
                        'x1' => [
                                  '99999',
                                  '22222'
                                ]
                      },
          'Puma' => {
                      'y1' => [
                                '33333'
                              ],
                      'x2' => [
                                '44444'
                              ],
                      'y2' => [
                                '55555'
                              ],
                      'x1' => [
                                '77777'
                              ]
                    },
 'Brooks' => {
                        'y1' => [
                                  '22222',
                                  '44444'
                                ],
                        'x2' => [
                                  '33333',
                                  '55555'
                                ],
                        'y2' => [
                                  '44444',
                                  '66666'
                                ],
                        'x1' => [
                                  '11111',
                                  '33333'
                                ]
                      }


 };

我的hash2:

$VAR1 = {
          'Adidas' => {
                        'y1' => [
                                  '11111',
                                  '88888'
                                ],
                        'x2' => [
                                  '33333',
                                  '55555'
                                ],
                        'y2' => [
                                  '44444',
                                  '77777'
                                ],
                        'x1' => [
                                  '11111',
                                  '99999'
                                ]
                      },
          'Puma' => {
                      'y1' => [
                                '33333'
                              ],
                      'x2' => [
                                '44444'
                              ],
                      'y2' => [
                                '55555'
                              ],
                      'x1' => [
                                '77777'
                              ]
                    },
 'Brooks' => {
                        'y1' => [
                                  '22222',
                                  '44444'
                                ],
                        'x2' => [
                                  '33333',
                                  '55555'
                                ],
                        'y2' => [
                                  '44444',
                                  '66666'
                                ],
                        'x1' => [
                                  '11111',
                                  '33333'
                                ]
                      }
        };

我的匹配和不匹配尝试代码:

 foreach my $newq (keys %hash1)
    {
         foreach my $oldq(keys %hash2)
         {
         if ( $newq eq $oldq)
         {
         foreach my $newx1(@{$hash1{$newq}{x1}})
         {
         foreach my $oldx1(@{$hash2{$oldq}{x1}})
         {
         if ($newx1 == $oldx1)
         {
         print "$newq\t$newx1\t$oldx1\n";
         }
         if ($newx1 != $oldx1)
         {
         print "$newq\t$newx1\t$oldx1\n";
         }
             }

我的匹配输出

         New     Old
Adidas  99999   99999
Puma    77777   77777
Brooks  11111   11111
Brooks  33333   33333

我的输出不匹配:

        New     Old
Adidas  99999   11111
Adidas  22222   11111
Adidas  22222   99999
Brooks  11111   33333
Brooks  33333   11111

匹配所需的输出:

                      New                           Old
Puma                77777 33333 44444 55555     77777 33333 44444 55555
Adidas              99999 88888 55555 77777     99999 88888 55555 77777
Brooks              11111 22222 33333 44444     11111 22222 33333 44444
Brooks              33333 44444 55555 66666     33333 44444 55555 66666


Not matching

Adidas              22222 11111 33333 44444     11111 11111 33333 44444

现在我可以获得x1的正确匹配。但是我得到了“不匹配”的错误输出。我对“不匹配”的预期输出是Adidas 22222 11111,仅因为在新数据和旧数据中都显示了'x1=> 99999'。而且我不确定如何继续使用“ y1,x2和y2” ...

1 个答案:

答案 0 :(得分:1)

x1,y1等...只是哈希中的键,因此您可以像获取任何哈希这样的键一样获得它们

keys %{$hash1{$newq}}

尽管有那么多循环的层,您不必使代码变得如此复杂。以这部分为例...

foreach my $newq (keys %hash1)
{
     foreach my $oldq(keys %hash2)
     {
         if ( $newq eq $oldq)
         {
             # ....
         }
     }
 }

您不需要遍历两个哈希,因为您可以测试看看另一个哈希中是否存在键。想象一下,如果您的每个哈希都有100个密钥。您的代码当前检查%hash2中的所有100个键和%hash1中的每个键,然后再次进行检查,因此进行了20000次测试。如果您这样编写代码...

foreach my $newq (keys %hash1)
{
    if(defined($hash2{$newq}))
    {
        # both hashes have this key
    }
    else
    {
        # %hash2 doesn't have the key
    }
}

foreach my $newq (keys %hash2)
{
    if(!defined($hash1{$newq}))
    {
        # %hash1 doesn't have the key
    }
    else
    {
        # They both do, but we already know that from the first loop
    }
}

...它只需要检查两个哈希中的每个键一次,因此只需200次检查。

所以最终完成的代码可能是:

my %nonmatching;
print "Matching\n";
foreach my $outerkey (keys %hash1)
{
    if(defined($hash2{$outerkey}))
    {
        foreach my $innerkey (keys %{$hash1{$outerkey}})
        {
            if(join(" ",sort @{$hash1{$outerkey}{$innerkey}}) eq join(" ",sort @{$hash2{$outerkey}{$innerkey}}))
            {
                 printf "%-20s %30s %30s\n",$outerkey, join(" ",@{$hash1{$outerkey}{$innerkey}}), join(" ",@{$hash2{$outerkey}{$innerkey}});
            } 
            else
            {
                 $nonmatching{$outerkey}{$innerkey}=1;
            }
        }
    }
    else
    {
        foreach my $innerkey (keys %{$hash1{$outerkey}})
        {
            $nonmatching{$outerkey}{$innerkey}=1;
        }
    }
}

foreach my $outerkey (keys %hash2)
{
    if(!defined($hash1{$outerkey}))
    {
        foreach my $innerkey (keys %{$hash2{$outerkey}})
        {
            $nonmatching{$outerkey}{$innerkey}=1;
        }
    }
}

print "Nonmatching\n";
foreach my $outerkey (keys %nonmatching)
{
    foreach my $innerkey (keys %{$nonmatching{$outerkey}})
    {
         printf "%-20s %30s %30s\n",$outerkey, join(" ",@{$hash1{$outerkey}{$innerkey}}), join(" ",@{$hash2{$outerkey}{$innerkey}});
    }
}

尽管您所声明的哈希值与源数据不匹配,所以输出看起来并不符合您的期望。我本来希望您的哈希看起来更像下面的代码片段,所以也许您的文件读取代码无法按照您的意愿工作?

'Adidas' => {
   'x1' => [
       '99999','88888','55555','77777'
    ]
  };