我对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方式做这个?
我对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;
效果会更好,因为这不会吃了你原来的字符串。
假设你想要的多个值相同的键是一个数组引用,然后做一个方式,它是这样的:
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'
]
};
Drats:你有重复键...我想用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}
值设定为到单个构件数组的引用。那是对的吗?
你实际上不需要行$ hash {$ key} = []如果不存在$ hash {$ key };'在所有。当你将第一个值推到它上面时,Perl会为你提供[autovivify](http://en.wikipedia.org/wiki/Autovivification)arrayref。 –
另外,你可以做'my($ key,$ value)= splice @array,0,2;'而不是两个'shift's。哦,和IMO的“分裂”;“'是误导,应该避免:'split'的第一个参数是一个正则表达式(除了'split'的特殊魔术情况''),即使你把它写成一个字符串。 –
我改变了'split'。这可能会产生误导。我也改变了拼接的双重转变。但是,我一直在将散列设置为空数组引用。它同时记录了我希望散列值是什么(对数组的引用),并且如果我输入错误的第一个值,它可以防止我意外地将其设置为散列引用。 –
也许最简单的(标准)的方式来做到这一点是List::MoreUtils::natatime
use List::MoreUtils qw<natatime>;
my $iter = natatime 2 => split /;/, 'xyz;1;xyz;2;a;2;b;2';
my %hash;
while (my ($k, $v) = $iter->()) {
push @{ $hash{ $k } }, $v;
}
但是抽象出来,我可能会想这样做的部分...
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');
如果你没有有重复的键,这将是微不足道的:'我的%散列=拆分/; /,$字符串;' –