如何在perl中忽略hash的键序列

时间:2018-05-23 09:03:02

标签: perl hash key

我有一个包含以下信息的文件

1:2=14
3:4=15
2:1=16
4:3=17

我想创建一个哈希处理密钥{1:2}与密钥{2:1}

相同的哈希
$hash{1:2} = $hash{2:1}

所以当我打印$hash{1:2}$hash{2:1}中的所有元素时,它会同时给我1416。这是一种简单的方法吗?

以下是我计划创建哈希

的密钥
for ( my $i = 0; $i <=$#file ; $i++) {
    my $line = $file[$i];
    my @key = split ("=",$line);
    my $hash{$key[0]} = $key[1];
}

1 个答案:

答案 0 :(得分:2)

没有内置的方法可以做到这一点。如果您的键遵循相同的模式,您可以将其包装在一个函数中,然后计算适合您的算法的所有键并获取值。

my %hash = (
    '1:2' => 14,
    '3:4' => 15,
    '2:1' => 16,
    '4:3' => 17,
);

sub get_elements {
    my ($key) = @_;

    return $hash{$key}, $hash{reverse $key}; # or $key =~ s/(\d+):(\d+)/$2:$1/r
}

print join ' ', get_elements('1:2');

这使用字符串reverse,显然只有在键的部分只有一位数时才有效。如果您的数字大于9,则必须拆分字符串并重新组合,或使用替换来切换它们。我的示例使用/r修饰符,该修饰符需要Perl 5.14 or higher

如果您想在阅读自动处理文件时构建数据结构,您也可以这样做。使用数组引用而不是哈希中的简单值,并将相同的引用分配给您想要相等的所有键。

use strict;
use warnings;
use feature 'say';
use Data::Dumper;

my %hash;
while (my $line = <DATA>) {
    chomp $line;
    my ($key, $value) = split /=/, $line;
    my ($left, $right) = split /:/, $key;

    # $hash{$key} //= ( $hash{"$right:$left"} // [] ); # needs 5.10
    $hash{$key} = ( $hash{"$right:$left"} || [] )
        unless exists $hash{$key};

    push @{ $hash{$key} }, $value;
}

say "@{ $hash{'1:2'} }";
say "@{ $hash{'2:1'} }";

print Dumper \%hash;

__DATA__
1:2=14
3:4=15
2:1=16
4:3=17

此代码的输出是

14 16
14 16

Data :: Dumper结构如下所示,它解释了键2:11:2都指向相同的数组引用。这意味着如果你将push另一个值放入其中一个中,它也会在另一个中结束,因为它们实际上是相同的。

$VAR1 = {
          '4:3' => [
                     '15',
                     '17'
                   ],
          '3:4' => $VAR1->{'4:3'},
          '2:1' => [
                     '14',
                     '16'
                   ],
          '1:2' => $VAR1->{'2:1'}
        };

唯一的缺点是你无法获得元素的顺序。此数据结构失去了1:2最初具有值142:1具有16的知识。如果您希望2:1输出16 14,则无效。