Perl - 具有修改后数据的新哈希项,源自另一个条目的馈线哈希,破坏了第一个条目

Perl - New Hash item with modified data, sourced from a feeder hash that sourced another entry, clobbers the first entry

我正在尝试添加一个哈希条目和一个新的、更新的哈希条目,它们来自相同的馈线哈希和原始数据。

但是,当我更新第二个条目的数据时...它破坏了原始条目...即使该数据没有更改...它只能更改,因为两者都是从相同的馈线哈希条目。

这是我为测试此问题而创建的测试程序中的示例子例程 - 它使用 Tk 进行输出...

sub hash_issue {
    my %feeder = ();
    my %global = ();
    my %personal = ();

    my $key = 'John';
    my $new_key = 'Johnathan';

    $feeder{$key}{First_Name} = 'John';
    $feeder{$key}{Last_Name} = '';
    $feeder{$key}{Address} = '123 Main Street';
    $feeder{$key}{City} = 'Springfield';
    $feeder{$key}{State} = '';
    $feeder{$key}{Zip} = '';
    $feeder{$key}{Is_Registered} = 0;
    
    $global{$key} = $feeder{$key};
    $main->Output->Append("First Name = $global{$key}{First_Name}  Last Name = $global{$key}{Last_Name}  Address = $global{$key}{Address}  Registered = $global{$key}{Is_Registered}\r\n");
    $global{$new_key} = $feeder{$key};
    $global{$new_key}{First_Name} = $new_key;
    $global{$new_key}{Is_Registered} = 1;
    $main->Output->Append("First Name = $global{$key}{First_Name}  Last Name = $global{$key}{Last_Name}  Address = $global{$key}{Address}  Registered = $global{$key}{Is_Registered}\r\n");
    $main->Output->Append("First Name = $global{$new_key}{First_Name}  Last Name = $global{$new_key}{Last_Name}  Address = $global{$new_key}{Address}  Registered = $global{$new_key}{Is_Registered}\r\n");
}

这是输出...

名字 = John 姓氏 = 地址 = 123 Main Street Registered = 0

名字 = Johnathan 姓氏 = 地址 = 123 Main Street Registered = 1

名字 = Johnathan 姓氏 = 地址 = 123 Main Street Registered = 1

(添加了额外的行以清理 post...)

我如何修改它以防止破坏原始条目...REAL 代码包含更多子散列键。

你的问题就在这里

$global{$new_key} = $feeder{$key};

这只是复制一个参考。如果你想要一个实际的副本,你需要克隆你的数据。

use Clone qw( clone );
$global{$new_key} = clone( $feeder{$key} );

请调查以下代码片段是否符合您的问题。

根据您的描述,我的理解是您尝试使用哈希 %feeder 值的副本创建新哈希 %global(以 $new_key 作为键),然后更改一些其中的值。

注意:%global 变量在子程序中的声明有些混乱

use strict;
use warnings;
use feature 'say';

hash_issue();

sub hash_issue {
    my(%feeder, %global);

    my $key = 'John';
    my $new_key = 'Johnathan';

    my @fields = (
                    'First_Name',
                    'Last_Name',
                    'Address',
                    'City',
                    'State',
                    'Zip',
                    'Is_Registered'
                 );
    my @values = (
                    'John',
                    '',
                    '123 Main Street',
                    'Springfield',
                    '',
                    '',
                    0
                 );

    @{$feeder{$key}}{@fields} = @values;

    @{$global{$new_key}}{@fields} = @{$feeder{$key}}{@fields};

    speak_out($key, \%feeder);
    speak_out($new_key, \%global);

    $global{$new_key}{First_Name} = $new_key;
    $global{$new_key}{Is_Registered} = 1;

    speak_out($new_key, \%global);
}

sub speak_out {
    my $key  = shift;
    my $data = shift;

    say "
        Key = $key
        ------------------------------------
        First Name = $data->{$key}{First_Name}
        Last Name  = $data->{$key}{Last_Name}
        Address    = $data->{$key}{Address}
        Registered = $data->{$key}{Is_Registered}
    ";
}

输出


        Key = John
        ------------------------------------
        First Name = John
        Last Name  =
        Address    = 123 Main Street
        Registered = 0


        Key = Johnathan
        ------------------------------------
        First Name = John
        Last Name  =
        Address    = 123 Main Street
        Registered = 0


        Key = Johnathan
        ------------------------------------
        First Name = Johnathan
        Last Name  =
        Address    = 123 Main Street
        Registered = 1

参考:Perl - Slices