1

我在下面有这两个哈希。第一个是模板,第二个是用户设置。

我需要能够创建一个遍历第二个哈希的循环,如果它发现差异(第一个中存在一个值,但第二个中不存在),那么它需要对该键和值做一些事情(让我们说 print它)

 $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'
                    ]
    };
4

3 回答 3

1

如果我正确理解了您的问题,那么只有当模板哈希中的项目不存在于用户的设置哈希中时,您才希望将模板哈希中的项目添加到用户设置的哈希中。

我们可以利用 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 的定义或( //=) 运算符,因为它遍历 的所有键%template,因此%userSettings如果键/值已经存在则不会更改,否则会更新。

希望这可以帮助!

于 2013-11-07T20:43:46.570 回答
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数组

使用 Perl 的两个数组的差异

于 2013-11-07T19:00:44.187 回答
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(复制粘贴)

于 2013-11-07T19:35:42.177 回答