Perl, разбить строку на ключ: пары значений для хэша с ключами в нижнем регистре без временного массива - PullRequest
0 голосов
/ 09 октября 2018

Учитывая строку пар Key: Value, я хочу создать поисковый хеш, но со строчными значениями для ключей.Я могу сделать это с помощью этого кода

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

Результирующий хэш будет выглядеть следующим образом:а или есть более эффективный способ достижения того же результата?

Редактировать: Я забыл упомянуть, что не могу использовать внешние модули для этого.Это должен быть базовый Perl.

Ответы [ 6 ]

0 голосов
/ 09 октября 2018

Больше возможных решений с использованием регулярных выражений для выполнения всей работы, но не очень красиво, если вы действительно не любите регулярные выражения:

use strict;
use warnings;
my $str="KEY1|Value1|kEy2|Value2|KeY3|Value3";
my %hash;
my $copy = $str;
$hash{lc $1} = $2 while $copy =~ s/^([^|]*)\|([^|]*)\|?//;

use strict;
use warnings;
my $str="KEY1|Value1|kEy2|Value2|KeY3|Value3";
my %hash;
$hash{lc $1} = $2 while $str =~ m/\G([^|]*)\|([^|]*)\|?/g;

use strict;
use warnings;
my $str="KEY1|Value1|kEy2|Value2|KeY3|Value3";
my %hash = map { my ($k, $v) = split /\|/, $_, 2; (lc($k) => $v) }
  $str =~ m/([^|]*\|[^|]*)\|?/g;
0 голосов
/ 09 октября 2018

Вот решение, которое позволяет избежать изменения входной строки, создания новой строки той же длины, что и входная строка, или создания промежуточного массива в памяти.

Решение здесь превращает split в циклнад оператором сопоставления.

#! /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 может распознавать и оптимизировать особый случай.Хотя на основании обсуждений здесь и здесь , я не уверен.

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;
}
0 голосов
/ 09 октября 2018

Для забавы, вот два дополнительных подхода.

Более дешевый, чем оригинал (поскольку элементы псевдонимы, а не скопированы в @_):

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

Ещедороже оригинала:

my %hash = ...;
@hash{ map lc, keys(%hash) } = delete( @hash{ keys(%hash) } );
0 голосов
/ 09 октября 2018
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);

Выход:

$VAR1 = {
          'key1' => 'Value1',
          'key2' => 'Value2',
          'key3' => 'Value3'
        };
0 голосов
/ 09 октября 2018

Вы можете использовать pairmap из List :: Util, чтобы сделать это вообще без промежуточного массива.

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;

Примечание: вы никогда не должны использовать $ a или $b вне блоков сортировки (или парной функции List :: Util).Они являются специальными глобальными переменными для сортировки, и простое объявление my $a в области может нарушить все виды (и парные функции List :: Util) в этой области.Простое решение - немедленно заменить их $x и $y всякий раз, когда вы начинаете использовать их в качестве примерных переменных.

0 голосов
/ 09 октября 2018

Поскольку пара ключ-значение должна быть около |, вы можете использовать регулярное выражение

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

my %h = split /\|/, $v =~ s/([^|]+) \| ([^|]+)/lc($1).q(|).$2/xger;
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...