Perl 从字符串生成哈希

Perl 从字符串生成哈希,perl,perl-data-structures,Perl,Perl Data Structures,我在perl上有以下字符串: my $string = xyz;1;xyz;2;a;2;b;2 我想为这个字符串构建一个如下所示的散列: my @array =split /;/,$string; $hash{xyz} =(1,2); $hash{b}=(2); $hahs{a}=(2); perl是如何做到这一点的 my $string = "xyz;1;xyz;2;a;2;b;2"; my %hash; push @{$hash{$1}}, $2 while $string =~ s

我在perl上有以下字符串:

my $string = xyz;1;xyz;2;a;2;b;2 
我想为这个字符串构建一个如下所示的散列:

my @array =split /;/,$string;

$hash{xyz} =(1,2);
$hash{b}=(2);
$hahs{a}=(2);
perl是如何做到这一点的

my $string = "xyz;1;xyz;2;a;2;b;2";
my %hash;
push @{$hash{$1}}, $2 while $string =~ s/^(\w+);(\d+);?//g;
实际上

push @{$hash{$1}}, $2 while $string =~ m/(\w+);(\d+);?/g;
这样会更好,因为这不会吃掉你原来的绳子

实际上

push @{$hash{$1}}, $2 while $string =~ m/(\w+);(\d+);?/g;

这样会更好,因为这不会耗尽原始字符串。

假设您希望同一个键的多个值成为数组引用,那么一种方法如下:

my @values = split /;/, $string;

my %hash;
while( @values ) { 
    my $key = shift @values;
    my $val = shift @values;

    if ( exists $hash{$key} && !ref $hash{$key} ) { 
        # upgrade to arrayref
        $hash{$key} = [ $hash{$key}, $val ];
    } elsif ( ref $hash{$key} ) { 
        push @{ $hash{$key} }, $val;
    } else { 
        $hash{$key} = $val;
    }
}
对于您的数据,这将导致如下结构

    {
      'a' => '2',
      'b' => '2',
      'xyz' => [
                 '1',
                 '2'
               ]
    };

假设希望同一个键的多个值成为数组引用,则一种方法如下:

my @values = split /;/, $string;

my %hash;
while( @values ) { 
    my $key = shift @values;
    my $val = shift @values;

    if ( exists $hash{$key} && !ref $hash{$key} ) { 
        # upgrade to arrayref
        $hash{$key} = [ $hash{$key}, $val ];
    } elsif ( ref $hash{$key} ) { 
        push @{ $hash{$key} }, $val;
    } else { 
        $hash{$key} = $val;
    }
}
对于您的数据,这将导致如下结构

    {
      'a' => '2',
      'b' => '2',
      'xyz' => [
                 '1',
                 '2'
               ]
    };

你有重复的钥匙。。。我想用map或grep做点什么

这很容易理解:

my $string = "xyz;1;xyz;2;a;2;b;2";
my @array = split /;/ => $string;

my %hash;
while (@array) {
    my ($key, $value) = splice @array, 0, 2;
    $hash{$key} = [] if not exists $hash{$key};
    push @{$hash{$key}}, $value;
}
即使您的字符串中的键不在一起,该程序也会工作。例如,即使xyz由其他值对分隔,以下操作仍有效:

my $string = "xyz;1;a;2;b;2;xyz;2";

我假设$hash{b}=2;表示希望$hash{b}的值作为对单个成员数组的引用。正确吗?

拖动:您有重复的键。。。我想用map或grep做点什么

这很容易理解:

my $string = "xyz;1;xyz;2;a;2;b;2";
my @array = split /;/ => $string;

my %hash;
while (@array) {
    my ($key, $value) = splice @array, 0, 2;
    $hash{$key} = [] if not exists $hash{$key};
    push @{$hash{$key}}, $value;
}
即使您的字符串中的键不在一起,该程序也会工作。例如,即使xyz由其他值对分隔,以下操作仍有效:

my $string = "xyz;1;a;2;b;2;xyz;2";

我假设$hash{b}=2;表示希望$hash{b}的值作为对单个成员数组的引用。对吗?

最简单的标准方法可能是

然而,提取出我可能想再次做的部分

use List::MoreUtils qw<natatime>;

sub pairs { 
    my $iter = natatime 2 => @_;
    my @pairs;
    while ( my ( $k, $v ) = $iter->()) { 
        push @pairs, [ $k, $v ];
    }
    return @pairs;
}

sub multi_hash {
    my %h;
    push @{ $h{ $_->[0] } }, $_->[1] foreach &pairs;
    return wantarray ? %h : \%h;
}

my %hash = multi_hash( split /;/, 'xyz;1;xyz;2;a;2;b;2' );

可能最简单的标准方法是

然而,提取出我可能想再次做的部分

use List::MoreUtils qw<natatime>;

sub pairs { 
    my $iter = natatime 2 => @_;
    my @pairs;
    while ( my ( $k, $v ) = $iter->()) { 
        push @pairs, [ $k, $v ];
    }
    return @pairs;
}

sub multi_hash {
    my %h;
    push @{ $h{ $_->[0] } }, $_->[1] foreach &pairs;
    return wantarray ? %h : \%h;
}

my %hash = multi_hash( split /;/, 'xyz;1;xyz;2;a;2;b;2' );

如果不存在$hash{$key},那么实际上不需要行$hash{$key}=[];完全当您将第一个值推到arrayref上时,Perl将为您创建arrayref;而不是两班倒。哦,我分手了;这是误导性的,应该避免:split的第一个参数是regexp,除了split这个特殊的神奇例子,即使你把它写成一个字符串。我已经更改了split。这有潜在的误导性。我还将双移位改为拼接。但是,我保留将哈希设置为空数组引用的位置。它既记录了我期望散列值是数组引用的内容,也防止了我在输入错误的第一个值时意外地将其设置为散列引用;完全当您将第一个值推到arrayref上时,Perl将为您创建arrayref;而不是两班倒。哦,我分手了;这是误导性的,应该避免:split的第一个参数是regexp,除了split这个特殊的神奇例子,即使你把它写成一个字符串。我已经更改了split。这有潜在的误导性。我还将双移位改为拼接。但是,我保留将哈希设置为空数组引用的位置。它既记录了我期望散列值是对数组的引用的内容,也防止了我在输入错误的第一个值时意外地将其设置为散列引用。如果没有重复的键,这将很简单:my%hash=split/;/$一串如果没有重复的键,那么这将很简单:my%hash=split/;/$一串