【问题标题】:How can I change the case of a hash key?如何更改哈希键的大小写?
【发布时间】:2010-09-23 12:46:34
【问题描述】:

我正在编写一个可能被用户修改的脚本。目前我将配置设置存储在脚本中。它以散列的形式存在。

我想防止人们在哈希键中意外使用小写字符,因为这会破坏我的脚本。

检查哈希键很简单,只需对任何带有小写字符的键发出警告,但我宁愿自动修复区分大小写。

也就是说,我想将顶级哈希中的所有哈希键都转换为大写。

【问题讨论】:

    标签: perl hash


    【解决方案1】:

    遍历哈希并将所有小写键替换为其大写等效项,并删除旧键。大致:

    for my $key ( grep { uc($_) ne $_ } keys %hash ) {
        my $newkey = uc $key;
        $hash{$newkey} = delete $hash{$key};
    }
    

    【讨论】:

      【解决方案2】:

      Andy 的答案是一个很好的答案,除了他ucs 每个键,如果不匹配则再次ucs。

      这个ucs 一次:

      %hash = map { uc $_ => $hash{$_} } keys %hash;
      

      但由于您提到了用户存储密钥,因此平局是一种更可靠的方式,即使速度较慢。

      package UCaseHash;
      require Tie::Hash;
      
      our @ISA = qw<Tie::StdHash>;
      
      sub FETCH { 
          my ( $self, $key ) = @_;
          return $self->{ uc $key };
      }
      
      sub STORE { 
          my ( $self, $key, $value ) = @_;
          $self->{ uc $key } = $value;
      }
      
      1;
      

      然后在 main:

      tie my %hash, 'UCaseHash'; 
      

      这是一个节目。 tie“魔术”封装了它,所以用户不会在不知不觉中乱用它。

      当然,只要你使用“类”,你可以传入配置文件名并从那里初始化它:

      package UCaseHash;
      use Tie::Hash;
      use Carp qw<croak>;
      
      ...
      
      sub TIEHASH { 
          my ( $class_name, $config_file_path ) = @_;
          my $self = $class_name->SUPER::TIEHASH;
          open my $fh, '<', $config_file_path 
              or croak "Could not open config file $config_file_path!"
              ;
          my %phash = _process_config_lines( <$fh> );
          close $fh;
          $self->STORE( $_, $phash{$_} ) foreach keys %phash;
          return $self;
      }
      

      你必须这样称呼它:

      tie my %hash, 'UCaseHash', CONFIG_FILE_PATH;
      

      ...假设一些常量CONFIG_FILE_PATH

      【讨论】:

      • 你知道,CPAN 上有一个模块可以做到这一点。无需自己编码:Hash::Case,见search.cpan.org/dist/Hash-Case
      • 你的方法会覆盖整个哈希,而安迪的方法只会覆盖小写的。除非您希望哈希包含大量可怕的小写键(在这种情况下不太可能),否则它不会更快。
      • 感谢您的提醒,巴特。我忘记了 Perl Club 的第一条规则:在检查 CPAN 之前不要说话。我的帖子一开始是一个捆绑类的简单插图,然后我就喜欢上了。哇!
      • 理解这一点,莱昂。但我不喜欢丢弃已经计算好的数据,这不一定与速度有关。我的表达方式更实用,IMO。
      【解决方案3】:

      这会将多级哈希转换为小写

      my $lowercaseghash = convertmaptolowercase(\%hash);
      
      sub convertmaptolowercase(){
          my $output=$_[0];
          while(my($key,$value) = each(%$output)){
              my $ref;
              if(ref($value) eq "HASH"){
                  $ref=convertmaptolowercase($value);
              } else {
                 $ref=$value;
              }
              delete $output->{$key}; #Removing the existing key
              $key = lc $key;
              $output->{$key}=$ref; #Adding new key
          }
          return $output;
      }
      

      【讨论】:

        猜你喜欢
        • 2013-06-04
        • 1970-01-01
        • 2010-09-23
        • 1970-01-01
        • 2016-09-04
        • 2021-12-07
        • 1970-01-01
        • 2015-09-28
        • 2011-06-24
        相关资源
        最近更新 更多