【问题标题】:evaluate entered postcodes against perl array根据 perl 数组评估输入的邮政编码
【发布时间】:2018-02-05 01:47:33
【问题描述】:

我有一个数组,其中包含 perl 中邮政编码区域的前 2 个字符,如下所示:

@acceptedPostcodes = ("CV", "LE", "CM", "CB", "EN", "SG", "NN", "MK", "LU", "PE", "ST", "TF", "DE", "WS");

我有一个搜索框,用户可以在其中输入部分或完整的邮政编码。我需要检查他们输入的邮政编码是否以数组的元素之一开头,例如,如果他们输入“CV2 1DH”,它会评估为真,如果他们输入类似“YO1 8WE”的东西,它会评估为假为它不以数组值之一开头。

现在这对我来说在 PHP 中很容易做到,但 Perl 并不是我擅长的东西,到目前为止我的努力还没有取得丰硕的成果。

有什么想法吗?

【问题讨论】:

  • 只是添加一个 .cgi 脚本,不确定这是否有任何区别。

标签: regex arrays perl


【解决方案1】:

如果您接受的邮政编码列表足够大,以至于匹配代码中的性能是一个实际问题(可能不是),那么您最好还是使用哈希查找而不是数组:

#!/usr/bin/perl

use strict;
use warnings;

my %accepted_postcodes = ("CV" => 1, "LE" => 1, "CM" => 1, "CB" => 1, "EN" => 1, "SG" => 1, "NN" => 1, "MK" => 1, "LU" => 1, "PE" => 1, "ST" => 1, "TF" => 1, "DE" => 1, "WS" => 1);
# Or, to be more terse:
# my %accepted_postcodes = map { $_ => 1 } qw(CV LE CM CB EN SG NN MK LU PE ST TF DE WS);

my $postcode = "CV21 1AA";

if (exists $accepted_postcodes{substr $postcode, 0, 2}) {
    print "$postcode is OK\n" ;
} else {
    print "$postcode is not OK\n";
}

此方法适用于 5.8.8。

【讨论】:

  • 不错,目前为止确实是最快的,即使是小数据集。
  • 尽管其他解决方案看起来很棒,但我还是选择了这个解决方案,只是因为它不需要太多玩弄就可以工作。好消息是我的邮政编码区域数据集只有大约 12-15,所以我不应该担心任何速度问题。感谢大家的回答。
【解决方案2】:

Smart Match (~~) 是您的朋友(在您使用 substr 获取输入字符串的前两个字母之后。

#!/usr/bin/perl

use strict;
use warnings;
use v5.10;

my @acceptedPostcodes = ("CV", "LE", "CM", "CB", "EN", "SG", "NN", "MK", "LU", "PE", "ST", "TF", "DE", "WS");

my $postcode = "CV21 1AA";

if ((substr $postcode, 0, 2) ~~ @acceptedPostcodes) {
    say "$postcode is OK" ;
} else {
    say "$postcode is not OK";
}

【讨论】:

  • 这仅适用于 Perl 5.10。
  • 早于 5.10 的 Perl 5 版本已停产,5.10 已被 5.12 取代。我今天真的不会针对 5.8 进行新的开发。
  • 我确定这是一个非常愚蠢的问题,但找出我使用的版本的最简单方法是什么?
  • 好吧,这是 perl, v5.8.8 为 x86_64-linux-thread-multi 构建的好消息还是坏消息?
  • 智能匹配的性能不是很好,每次都必须遍历整个列表。因为它是一个静态列表,而且你要做很多工作,所以最好把它变成一个散列。
【解决方案3】:

好的,一个老式的 foreach 版本,注意它会区分大小写。 有趣的是,基准测试与 ~~ 版本大致相同。

sub validatePostcode($)
{
  my ($testPostcode) = @_;
  my @acceptedPostcodes = ("CV", "LE", "CM", "CB", "EN", "SG", "NN", "MK", "LU", "PE", "ST", "TF", "DE", "WS");

  $testPostcode = substr($testPostcode, 0, 2);
  foreach my $postcode (@acceptedPostcodes)
  {
   if($postcode eq $testPostcode)
   {
    return 1;
   }
  }

  return 0;
}

【讨论】:

    【解决方案4】:

    您可以使用List::Utilfirst,或grep 内置:

    use List::Util 'first';
    
    my $postcode = substr $input, 0, 2;    
    my $status = (first {$_ eq $postcode} @acceptedPostcodes) ? 1 : 0;
    

    【讨论】:

    • 标记它是正确的,但它的基准测试比 foreach 和 ~~ 解决方案慢得多。
    • @JonB: List::Util 是用 C 写的,为了速度,所以不会比 grep/foreach/~~ 慢很多。
    • 我刚试过。这是一个最小的基准,但在 2000000 次迭代中,我得到了大约 35 秒的 foreach 和 ~~ 但 List::Util 达到了 60 左右。
    • @JonB 如果我不得不猜测为什么智能匹配更快,List::Util 仍然必须在每个元素上运行 Perl 子例程。智能匹配可以完全停留在 C 内部。当它们击中第一个元素时,它们都会停止。智能匹配这么快,对数组的大小影响不大,40个元素也就是400万个,而List::Util的速度比线性的慢,必须承受传入数组的开销。如果您有 5.10,请使用智能匹配。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-12-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-09-14
    相关资源
    最近更新 更多