我得检查一下像这个一样的hashrefs
{ foo => 65, bar => 20, baz => 15 }针对一列表示这样条件的hashref
[
{ foo => { "<=" => 75 } },
{ bar => { "==" => 20 } },
{ baz => { ">=" => 5 } },
]如果满足所有条件,则返回一个真值。
这两种数据结构都不是预先确定的。一个是通过解析数据库中的字符串构建的,另一个是通过解析用户输入构建的。
在上述情况下,我将返回true,但如果我检查hashref与
[
{ foo => { "<=" => 60 } },
{ bar => { "==" => 20 } },
{ baz => { ">=" => 5 } },
]我会返回false,因为第一个hashref中的foo不是<= 60。
问题是:做这件事的最佳策略是什么?
我在想
我是不是走错路了?如果不是,什么是最好的,最早的或预先构建的函数?
我研究了Params::Validate,但我担心这会导致大量开销,而且无论如何我都必须构建回调。
发布于 2012-03-04 11:21:22
改用代码引用,您就可以使用验证器了。我简化了你的条件-结构。这里不需要额外的数组级别,除非您有重复的散列键,我假设您没有。
简化的sub { $_[0] <= 75 }将简单地比较参数的第一个值。默认情况下,子例程中的最后一个值将是它的返回值。
use v5.10;
use strict;
use warnings;
my $in = { foo => 65, bar => 21, baz => 15 };
my $ref = {
foo => sub { $_[0] <= 75 } ,
bar => sub { $_[0] == 20 } ,
baz => sub { $_[0] >= 5 } ,
};
for my $key (keys %$in) {
if ($ref->{$key}($in->{$key})) {
say "$key : Valid";
} else {
say "$key : Invalid";
}
}输出:
bar : Invalid
baz : Valid
foo : Valid发布于 2012-03-04 12:33:59
为了基于TLP的答案,您还可以轻松地从现有的散列数组中创建匿名子类:
my $array_of_hashes = [
{ foo => { "<=" => 75 } },
{ bar => { "==" => 20 } },
{ baz => { ">=" => 5 } },
];
my $ref = {};
foreach my $entry ( @$array_of_hashes ) {
my ($key, $subhash) = %$entry;
my ($op, $num) = %$subhash;
$ref->{$key} = {
'<=' => sub { $_[0] <= $num },
'==' => sub { $_[0] == $num },
'>=' => sub { $_[0] >= $num },
}->{$op};
}这假设您只对原始散列数组中的每个字段进行一次检查。如果您有几个,事情会变得更棘手,但您总是可以这样做:
my $ref = {};
foreach my $entry ( @$array_of_hashes ) {
my ($key, $subhash) = %$entry;
my ($op, $num) = %$subhash;
my $chain = $ref->{$key} || sub {1};
$ref->{$key} = {
'<=' => sub { $_[0] <= $num and $chain->($_[0]) },
'==' => sub { $_[0] == $num and $chain->($_[0]) },
'>=' => sub { $_[0] >= $num and $chain->($_[0]) },
}->{$op} || $chain;
}Ps。如果有人想知道这段代码如何工作,答案是:闭包。具体来说,当这些匿名子在循环中创建时,它们保留对词法变量$num和$chain的引用,即使这些变量在当前循环迭代结束时超出了范围。因此,在此之后,这些变量将被安全地保存起来,只能从我们创建的子程序中访问。
https://stackoverflow.com/questions/9554206
复制相似问题