Perl比较2个哈希差异

时间:2013-11-07 18:30:13

标签: perl hash

我有以下两个哈希值。第一个是模板,第二个是用户设置。

我需要能够创建一个遍历第二个哈希的循环,如果它找到了差异(第一个中存在一个值而不是第二个中存在一个值),那么它需要对该键进行一些操作。价值(让我们说打印吧)

 $VAR1 = {
      'Hotkeys' => [
                     'key',
                     'keyCR',
                     'keyHighlight',
                     'updated'
                   ],
      'Actions' => [
                     'action',
                     'actionCR',
                     'actionHighlight'
                   ],
      'Settings' => [
                      'chbAcronym',
                      'chbCompleted'
                    ],
      'NewSetting' => [
                        'NewValue'
                      ]
    };

$VAR1 = {
      'Hotkeys' => [
                     'key',
                     'keyCR',
                     'keyHighlight'
                   ],
      'Actions' => [
                     'action',
                     'actionCR',
                     'actionHighlight'
                   ],
      'Settings' => [
                      'chbAcronym',
                      'chbCompleted'
                    ]
    };

3 个答案:

答案 0 :(得分:1)

迭代键并比较匹配键的数组。

sub my_special_hash_diff {

  my(%hash_A,%hash_B) = (@_) ; #This may need some tweaking, you probably need 
                               # need to pass in Hash references. 
  for $key ( keys %hash_B ) {

     @array1 = $hash_B{$key} ; 
     @array2 = $hash_A{$key} ; 
     compare_2_arrays(@array1,@array2) ; # See answer below. 
  }


}

如何比较两个perl数组

Difference of Two Arrays Using Perl

答案 1 :(得分:1)

如果我正确理解您的问题,您只想在用户设置哈希中不存在模板哈希中的项目时,才能将模板哈希中的项目添加到用户设置'hash

我们可以利用Perl的Autovivification,如果该哈希中的项目不存在,它将在用户设置'哈希中创建完整的数据结构。请考虑以下事项:

use strict;
use warnings;
use Data::Dumper;

my %template = (
    'Hotkeys'    => [ 'key',        'keyCR',    'keyHighlight', 'updated' ],
    'Actions'    => [ 'action',     'actionCR', 'actionHighlight' ],
    'Settings'   => [ 'chbAcronym', 'chbCompleted' ],
    'NewSetting' => [ 'NewValue' ]
);

my %userSettings = (
    'Hotkeys'  => [ 'key',        'keyCR',        'keyHighlight' ],
    'Actions'  => [ 'action',     'actionCR',     'actionHighlight' ],
    'Settings' => [ 'chbAcronym', 'chbCompleted', 'aUserSetting' ]
);

updateUserSettings( \%template, \%userSettings );
print Dumper \%userSettings;

sub updateUserSettings {
    my ( $templateHash, $settingsHash ) = @_;

    for my $key ( keys %$templateHash ) {
        $settingsHash->{$key}->[$_] //= $templateHash->{$key}->[$_]
          for 0 .. $#{ ${$templateHash}{$key} };
    }
}

输出('更新'后转储%userSettings):

$VAR1 = {
          'Hotkeys' => [
                         'key',
                         'keyCR',
                         'keyHighlight',
                         'updated'
                       ],
          'Actions' => [
                         'action',
                         'actionCR',
                         'actionHighlight'
                       ],
          'NewSetting' => [
                            'NewValue'
                          ],
          'Settings' => [
                          'chbAcronym',
                          'chbCompleted',
                          'aUserSetting'
                        ]
        }

请注意,%userSettings仅在缺少%template信息的情况下进行更新,并且不会打扰任何其他内容。

子例程updateUserSettings使用Perl的 defined-或//=)运算符,因为它遍历%template的所有键,因此%userSettings如果键/值已经存在,则不会更改,否则会更新。

希望这有帮助!

答案 2 :(得分:0)

假设第一个散列(模板)包含第二个散列(模板)可能具有的所有可能值,您可以使用此方法,这可能不是最有效但很简单且不需要外部模块:

use strict;

my $template = {
      'Hotkeys' => [
                     'key',
                     'keyCR',
                     'keyHighlight',
                     'updated'
                   ],
      'Actions' => [
                     'action',
                     'actionCR',
                     'actionHighlight'
                   ],
      'Settings' => [
                      'chbAcronym',
                      'chbCompleted'
                    ],
      'NewSetting' => [
                        'NewValue'
                      ]
    };

my $user = {
      'Hotkeys' => [
                     'key',
                     'keyCR',
                     'keyHighlight'
                   ],
      'Actions' => [
                     'action',
                     'actionCR',
                     'actionHighlight'
                   ],
      'Settings' => [
                      'chbAcronym',
                      'chbCompleted'
                    ]
    };

#take all user keys so that we don't perform a join in each iteration
my $all_user_keys = join(' ',keys %$user);
#loop all template keys to see what's missing from user keys
foreach my $template_key( keys %$template ) {
    #this will return a true value if the template key also exists in user hash
    my $key_exists_in_user = ( $all_user_keys =~ m/$template_key/ );
    #if it exists, perform a second loop for the values of the array
    if ($key_exists_in_user) {
        #take all user values so that we don't perform a join in each iteration
        my $all_user_values_of_key = join(' ', @{$user->{$template_key}});
        #loop all values of template key, to see what's missing from user values
        foreach my $template_key_value (@{$template->{$template_key}}) {
            #if value is not found, do what you want with it
            unless( $all_user_values_of_key =~ m/$template_key_value/ ) {
                print "  -- value '$template_key_value' does not exist in user key '$template_key'. will add it now\n";
                push @{$user->{$template_key}}, $template_key_value;
            }
        }
    #else, hash key is not found, so do what you want with it
    } else {
        print "hash key '$template_key' does not exist in user settings. Will add it now\n";
        $user->{$template_key} = $template->{$template_key};
    }
}

我使用了你的示例哈希,我还假设你的哈希实际上是hashrefs(复制粘贴原样)