Проверьте, присутствует ли часть строки в ключах хеш-таблицы - PullRequest
1 голос
/ 17 апреля 2019

Я имею дело с хеш-таблицей в Perl.

У меня есть несколько строк, с несколькими длинами и несколькими -:

pre1-pre2-text1-text2
pre3-text3
pre4-pre5-pre6-text4

У меня есть %hashсо следующими ключами:

pre1-pre2
pre3
pre4-pre5-pre6

Таким образом, ключи %hash содержат только часть строк pre.

Как я могу проверить, есть ли совпадение, скажем,первая строка pre1-pre2-text1-text2 и ключи %hash?

Ответы [ 3 ]

2 голосов
/ 18 апреля 2019

Один способ: сформировать шаблон, используя чередование ключей, и протестировать строки с ним

use warnings;
use strict;
use feature 'say';

my @strings = qw(pre-not pre1-pre2-text1-text2 pre3-text3 pre4-pre5-pre6-text4);

my %h = ( 'pre1-pre2' => 1, 'pre3' => 1, 'pre4-pre5-pre6' => 1 );

my $keys_re = join '|', map { quotemeta } keys %h; 

foreach my $str (@strings) { 
    say $str  if $str =~ /$keys_re/;
}

Это имеет квадратичную сложность, но чередование не будет проходить через все ключи и его C (регулярное выражение само).

Возможное улучшение (или необходимость!) Может заключаться в надлежащей сортировке ключей.Например, самый короткий первый

my $keys_re = join '|', map { quotemeta } sort { length $a <=> length $b } keys %h; 

Это может помочь, если есть ключи с общими частями, но учтите, что это может быть нетривиальная настройка, которая может повлиять на правильность - и какая может потребоваться;Тщательно продумайте.

Чтобы также получить сам ключ, добавьте круглые скобки вокруг шаблона

foreach my $str (@strings) { 
    say "$str matched by key: $1"  if $str =~ /($keys_re)/;
}

, где $1 содержит чередование, которое совпало и было получено, что является ключом.

1 голос
/ 17 апреля 2019

Этот ответ предполагает, что pre не может происходить в середине строки (т. Е. У вас не будет такой строки, как pre1-pre2-text1-pre5, где ваш префикс будет только pre1-pre2).Если это предположение неверно, тогда используйте /^((?:pre\d+)(?:-pre\d+)*)/ вместо /^(.*pre\d+)/ (я предпочитаю второе, потому что оно более читабельно, но первое более точно).

#!/usr/bin/perl

use strict;
use warnings;
use feature 'say';

my %pre = map { $_ => 1 } qw(pre1-pre2 pre3 pre4-pre5-pre6);

while (<DATA>) {
    my ($prefix) = /^(.*pre\d+)/;
    if ($prefix && exists $pre{$prefix}) {
        say "Prefix exists: $prefix";
    } else {
        say "Prefix doesn't exist: $prefix";
    }
}

__DATA__
pre1-pre2-text1-text2
pre3-text3
pre4-pre5-pre6-text4
pre7-pre8-text5

Если бы вы могли иметьстрока pre1-pre2-text1, где префикс должен быть просто pre1, тогда это решение не будет работать.В этом случае у вас не будет другого выбора, кроме как перебирать все ключи хэша и проверять, соответствуют ли они началу строки:

while (<DATA>) {
    for my $prefix (keys %pre) {
        if (/^\Q$prefix/) {
            say "Found prefix: $prefix";
            last;
        }
    }
}

Однако это гораздо менее эффективно, так каквам нужно перебрать все ключи хеш-функции для каждой строки.
Относительно \Q: это гарантирует, что это решение работает, даже если ваши префиксы содержат специальные символы регулярного выражения (например, + или .).Если ваши префиксы всегда похожи на pre1-pre2, то вы можете опустить \Q.


Если у вас возникли проблемы с пониманием my %pre = map { $_ => 1 } qw(pre1-pre2 pre3 pre4-pre5-pre6);: это краткая версия

my %prev = (
    'pre1-pre2'      => 1,
    'pre3'           => 1,
    'pre4-pre5-pre6' => 1
);
1 голос
/ 17 апреля 2019

Я добавил введенные вами данные в небольшом perl-коде, и я могу проверить, есть ли совпадение в ключах

#!/usr/bin/perl
use warnings;

my %langs = ( "pre1-pre2" => 'pre1-pre2',
 "pre3" => 'pre3',
 "pre4-pre5-pre6" => 'pre4-pre5-pre6');

@pats=("pre1-pre2-text1-text2", "pre3-text3", "pre4-pre5-pre6-text4");

for(keys %langs){
  foreach $ss (@pats){
    if (index($ss,$_) != -1){
      print("Key contains:",$_, "|", $ss,"\n");
    }
    else{
      print("NOT FOUND:",$_, "|", $ss,"\n");
    }
  }
}

ПРИМЕЧАНИЕ. Если я правильно понял ваше требование, то это поможет вам.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...