如何在Perl中将字符串拆分为多个哈希键

时间:2018-07-15 17:05:35

标签: perl split hashmap

例如,我有一系列字符串

my @strings;
$strings[1] = 'foo/bar/some/more';
$strings[2] = 'also/some/stuff';
$strings[3] = 'this/can/have/way/too/many/substrings';

我想做的就是拆分这些字符串,并将它们存储在哈希中,作为这样的键

my %hash;
$hash{foo}{bar}{some}{more} = 1;
$hash{also}{some}{stuff} = 1;
$hash{this}{can}{have}{way}{too}{many}{substrings} = 1;

我可以继续列出失败的尝试,但是我认为它们不会增加问题的价值,但我会提到其中一个。可以说我将'foo/bar/some/more'转换为'{foo}{bar}{some}{more}'。我可以以某种方式将其存储在变量中并执行以下操作吗?

my $var = '{foo}{bar}{some}{more}';
$hash$var = 1;

注意:这不起作用,但我希望这不是因为语法错误。

感谢所有帮助。

4 个答案:

答案 0 :(得分:5)

与肖恩的答案完全相同的逻辑。但是我已经在子例程中隐藏了巧妙的散列查询功能。而且我将最终值设置为1,而不是空的哈希引用。

#!/usr/bin/perl

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

use Data::Dumper;

my @keys = qw(
  foo/bar/some/more
  also/some/stuff
  this/can/have/way/too/many/substrings
);

my %hash;

for (@keys) {
  multilevel(\%hash, $_);
}

say Dumper \%hash;

sub multilevel {
  my ($hashref, $string) = @_;

  my $curr_ref = $hashref;
  my @strings = split m[/], $string;
  for (@strings[0 .. $#strings - 1]) {
    $curr_ref->{$_} //= {};
    $curr_ref = $curr_ref->{$_};
  }

  $curr_ref->{@strings[-1]} = 1;
}

答案 1 :(得分:4)

您必须使用哈希引用来遍历键列表。

use Data::Dumper;

my %hash = ();

while( my $string = <DATA> ){
    chomp $string;
    my @keys = split /\//, $string;
    my $hash_ref = \%hash;
    for my $key ( @keys ){
        $hash_ref->{$key} = {};
        $hash_ref = $hash_ref->{$key};
    }
}
say Dumper \%hash;

__DATA__
foo/bar/some/more
also/some/stuff
this/can/have/way/too/many/substrings

答案 2 :(得分:0)

只需使用一个库即可。

use Data::Diver qw(DiveVal);
my @strings = (
    undef,
    'foo/bar/some/more',
    'also/some/stuff',
    'this/can/have/way/too/many/substrings',
);
my %hash;
for my $index (1..3) {
    my $root = {};
    DiveVal($root, split '/', $strings[$index]) = 1;
    %hash = (%hash, %$root);
}
__END__
(
    also => {some => {stuff => 1}},
    foo  => {bar => {some => {more => 1}}},
    this => {can => {have => {way => {too => {many => {substrings => 1}}}}}},
)

答案 3 :(得分:0)

我采用了'eval'的简单方法:

use Data::Dumper;

%hash = ();
@strings = ( 'this/is/a/path', 'and/another/path', 'and/one/final/path' );
foreach ( @strings ) {
    s/\//\}\{/g;
    $str = '{' . $_ . '}';      # version 2: remove this line, and then
    eval( "\$hash$str = 1;" );  #   eval( "\$hash{$_} = 1;" );
}

print Dumper( %hash )."\n";