【问题标题】:Inverting a hash of arrays反转数组的哈希
【发布时间】:2015-11-27 23:46:42
【问题描述】:

我知道如果你这样做,可能会发生冲突。但是给定一个数组哈希:

my %transform = ( 
    'FF0000' => [qw ( error errors assertion )],
    'FFFF00' => [qw ( warning warnings paused )],
    '008000' => [qw ( active )],
);

我想把它变成一个搜索和替换正则表达式。

例如

my %colour_map = ( 
   'error' => 'FF0000',
   'errors' => 'FF0000',
   'assertion' => 'FFFF00',
   'warning' => 'FFFF00',
   'warnings' => 'FFFF00',
   'paused' => 'FFFF00',
   'active' => '008000',
);

my $search = join( "|", map {quotemeta} keys %colour_map ); 
   $search = qr/\b($search)\b/;

这样我可以:

while (<$fh>) {
    if ( my ($match) = m/$search/i ) {
        print "$colour_map{lc($match)} $match\n";
    }
}

我可以接受潜在的冲突(给定数组不需要唯一性)。

到目前为止,我得到了:

my %colour_map ;
foreach my $colour ( keys %replace ) {
   foreach my $value ( @{$replace{$colour}} ) {
        $colour_map{$value} = $colour;
   }
}

我认为应该使用类似map 的解决方案,但我想不通。

【问题讨论】:

  • 您将元字符添加到以下列表的可能性有多大:“错误”、“错误”、“断言”、“警告”、“警告”、“暂停”和“活动” ?鉴于趋势和建议的数据空间,我认为quotemeta 有点过头了,但这里可能存在商店标准。

标签: arrays perl hash perl-data-structures


【解决方案1】:

我不会太专注于“仅仅为了它而使用map 之类的东西”。如果您在设计以这种方式工作的解决方案时遇到问题,那么当您设法将脚塞进拖鞋时,其他人可能无法理解它的作用

我相信这是使用while 迭代器和each 最清晰和最简单的方法

这样

use strict;
use warnings;

use Data::Dump;

my %transform = (
    'FF0000' => [qw ( error errors assertion )],
    'FFFF00' => [qw ( warning warnings paused )],
    '008000' => [qw ( active )],
);

my %colour_map;

while ( my ($key, $val) = each %transform ) {
    $colour_map{$_} = $key for @$val;
}

dd \%colour_map;

输出

{
  active    => "008000",
  assertion => "FF0000",
  error     => "FF0000",
  errors    => "FF0000",
  paused    => "FFFF00",
  warning   => "FFFF00",
  warnings  => "FFFF00",
}

【讨论】:

    【解决方案2】:

    您可能想在此处使用双 map

    my %result = map { 
        my $k = $_;
        map { ( $_ => $k ) } @{$transform{$_}}
    } keys %transform;
    

    由于我们要在map 中调用map,因此必须将上下文变量保存到词法中。但是,对于来自List::Utilpairmap,情况并非如此:

    use List::Util qw<pairmap>;
    ...
    my %result = pairmap { map { ( $_ => $a ) } @$b } %transform;
    

    ...因为$a$b 已经设置为局部变量。

    【讨论】:

    • 啊,是的,这正是我要找的东西。
    【解决方案3】:

    不能说我会推荐这样做,但可以使用哈希切片来处理单个映射。

    my %color_map = (); # merica
    map { @color_map{ @{ $transform{ $_ } } } = ($_) x @{ $transform{ $_ } } } keys %transform;
    

    【讨论】:

      【解决方案4】:

      使用数组引用而不是数组来定义您的原始颜色关键字映射,因为 perl 不会创建您期望的散列。

      #!/usr/bin/env perl
      
      use strict;
      use warnings;
      use Data::Dumper;
      
      my %transform = ( 
          'FF0000' => [ qw ( error errors assertion ) ],
          'FFFF00' => [ qw ( warning warnings paused ) ], 
          '008000' => [ qw ( active ) ], 
      );
      
      my %color_map = map {
          my ($color) = $_;
          map { $_ => $color } @{ $transform{$color} };
      } keys %transform;
      
      print "Original Hash\n";
      print Dumper \%transform;
      print "Colormap from Hash\n";
      print Dumper \%color_map;
      

      输出

      Original Hash
      $VAR1 = {
            '008000' => [
                          'active'
                        ],
            'FFFF00' => [
                          'warning',
                          'warnings',
                          'paused'
                        ],
            'FF0000' => [
                          'error',
                          'errors',
                          'assertion'
                        ]
          };
      Colormap from Hash
      $VAR1 = {
            'warnings' => 'FFFF00',
            'assertion' => 'FF0000',
            'errors' => 'FF0000',
            'error' => 'FF0000',
            'warning' => 'FFFF00',
            'active' => '008000',
            'paused' => 'FFFF00'
          };
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2011-05-30
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-10-29
        • 2015-04-23
        • 2019-10-27
        • 2019-05-23
        相关资源
        最近更新 更多