Perl,将字符串拆分为Key:Value对,用于使用小写键的哈希(没有临时数组)

时间:2018-10-08 22:19:55

标签: perl hash

给定一串Key:Value对,我想创建一个查找哈希,但是键的小写值。我可以使用此代码

my $a="KEY1|Value1|kEy2|Value2|KeY3|Value3";
my @a = split '\|', $a;
my %b = map { $a[$_] = (  !($_ % 2) ? lc($a[$_]) : $a[$_])  } 0 .. $#a ;

生成的哈希看起来像这样的Dumper输出:

$VAR1 = {
          'key3' => 'Value3',
          'key2' => 'Value2',
          'key1' => 'Value1'
        };

是否可以在不使用临时数组@a的情况下直接创建哈希%b,还是有一种更有效的方法来实现相同的结果?

编辑:我忘了提到我不能为此使用外部模块。它必须是基本的Perl。

6 个答案:

答案 0 :(得分:5)

您可以使用List :: Util中的pairmap来完成此操作,而无需任何中间数组。

use strict;
use warnings;
use List::Util 1.29 'pairmap';
my $str="KEY1|Value1|kEy2|Value2|KeY3|Value3";
my %hash = pairmap { lc($a) => $b } split /\|/, $str;

注意:切勿在排序(或List :: Util对函数)块之外使用$a or $b。它们是用于排序的特殊全局变量,仅在范围内声明my $a可能会破坏该范围内的所有排序(以及List :: Util对函数)。一个简单的解决方案是,每当发现自己开始将它们用作示例变量时,立即用$x$y替换它们。

答案 1 :(得分:2)

由于键值对必须位于|附近,因此您可以使用正则表达式

my $v = "KEY1|Value1|kEy2|Value2|KeY3|Value3";

my %h = split /\|/, $v =~ s/([^|]+) \| ([^|]+)/lc($1).q(|).$2/xger;

答案 2 :(得分:1)

if (this.sourceList.some(x => x.Value === "L7") &&
    this.selectedSources.some(x => x.Value === "L0")) {
  ...
}

输出:

use strict;
use warnings;

use Data::Dumper;

my $i;
my %hash = map { $i++ % 2 ? $_ : lc } split(/\|/, 'KEY1|Value1|kEy2|Value2|KeY3|Value3');

print Dumper(\%hash);

答案 3 :(得分:1)

为了娱乐,这里还有另外两种方法。

比原始便宜(因为元素被别名而不是复制到@_中):

my %hash = sub { map { $_ % 2 ? $_[$_] : lc($_[$_]) } 0..$#_ }->( ... );

比原来的贵:

my %hash = ...;
@hash{ map lc, keys(%hash) } = delete( @hash{ keys(%hash) } );

答案 4 :(得分:1)

使用正则表达式来完成所有工作的更多可能解决方案,但是除非您非常喜欢正则表达式,否则不会很漂亮:

ptr[3]

答案 5 :(得分:0)

这里的解决方案避免了变异输入字符串,构造与输入字符串长度相同的新字符串或在内存中创建中间数组。

此处的解决方案将split更改为对match语句的循环。

#! /usr/bin/env perl

use strict;
use warnings;
use Data::Dumper;

my $a="KEY1|Value1|kEy2|Value2|KeY3|Value3";

sub normalize_alist_opt {
  my ($input) = @_;

  my %c;
  my $last_key;
  while ($input =~ m/([^|]*(\||\z)?)/g) {
    my $s = $1;
    next unless $s ne '';
    $s =~ s/\|\z//g;
    if (defined $last_key) {
      $c{ lc($last_key) } = $s;
      $last_key = undef;
    } else {
      $last_key = $s;
    }
  }

  return \%c;
}

print Dumper(normalize_alist_opt($a));

直接在split上运行的潜在解决方案。 Perl 可能可以识别并优化特殊情况。尽管基于讨论herehere,但我不确定。

sub normalize_alist {
  my ($input) = @_;

  my %c;
  my $last_key;
  foreach my $s (split /\|/, $input) {
    if (defined $last_key) {
      $c{ lc($last_key) } = $s;
      $last_key = undef;
    } else {
      $last_key = $s;
    }
  }

  return \%c;
}