我正在处理我之前发布的问题(here),并尝试将答案转换为子,以便我可以多次使用它。不确定它是否正确完成。任何人都可以提供更好或更清洁的子?
我有很多编程经验,但我的主要语言是PHP。知道如何用一种语言执行,但却无法在另一种语言中执行,这令人沮丧。
sub search_for_key
{
my ($args) = @_;
foreach $row(@{$args->{search_ary}}){
print "@$row[0] : @$row[1]\n";
}
my $thiskey = NULL;
my @result = map { $args->{search_ary}[$_][0] } # Get the 0th column...
grep { @$args->{search_in} =~ /$args->{search_ary}[$_][1]/ } # ... of rows where the
0 .. $#array; # first row matches
$thiskey = @result;
print "\nReturning: " . $thiskey . "\n";
return $thiskey;
}
search_for_key({
'search_ary' => $ref_cam_make,
'search_in' => 'Canon EOS Rebel XSi'
});
--- ---编辑
从目前为止的答案中,我拼凑了下面的功能。我是 new 到Perl,所以我真的不太了解语法。我所知道的是它会抛出一个关于grep线的错误(不是第26行的ARRAY引用)。
由于我似乎没有提供足够的信息,我也会提到:
我正在调用此函数(可能是也可能不正确):
search_for_key({
'search_ary' => $ref_cam_make,
'search_in' => 'Canon EOS Rebel XSi'
});
$ ref_cam_make是我从数据库表中收集的数组,如下所示:
$ref_cam_make = $sth->fetchall_arrayref;
它是在这样的结构中(如果我理解如何使关联提取正常工作,我想用它而不是数字键):
Reference Array
Associative
row[1][cam_make_id]: 13, row[1][name]: Sony
Numeric
row[1][0]: 13, row[1][1]: Sony
row[0][0]: 19, row[0][1]: Canon
row[2][0]: 25, row[2][1]: HP
sub search_for_key
{
my ($args) = @_;
foreach my $row(@{$args->{search_ary}}){
print "@$row[0] : @$row[1]\n";
}
print grep { $args->{search_in} =~ @$args->{search_ary}[$_][1] } @$args->{search_ary};
}
答案 0 :(得分:5)
您正朝着2D数组的方向移动,其中[0]
元素是某种ID号,而[1]
元素是相机制作的。虽然这种方法快速而肮脏,但很快就会导致代码难以理解。如果您使用更丰富,更具说明性的数据结构,您的项目将更容易维护和发展。
以下示例使用哈希引用来表示相机品牌。更好的方法是使用对象。当您准备好采取这一步骤时,请查看Moose。
use strict;
use warnings;
demo_search_feature();
sub demo_search_feature {
my @camera_brands = (
{ make => 'Canon', id => 19 },
{ make => 'Sony', id => 13 },
{ make => 'HP', id => 25 },
);
my @test_searches = (
"Sony's Cyber-shot DSC-S600",
"Canon cameras",
"Sony HPX-32",
);
for my $ts (@test_searches){
print $ts, "\n";
my @hits = find_hits($ts, \@camera_brands);
print ' => ', cb_stringify($_), "\n" for @hits;
}
}
sub cb_stringify {
my $cb = shift;
return sprintf 'id=%d make=%s', $cb->{id}, $cb->{make};
}
sub find_hits {
my ($search, $camera_brands) = @_;
return grep { $search =~ $_->{make} } @$camera_brands;
}
答案 1 :(得分:4)
整个sub真的很混乱,而且我是一个相当普通的perl用户。以下是一些全面的建议。
undef
- 使用undef
然后在底部return $var // 'NULL'
返回。foreach $row
,因为foreach my $row
不太容易造成问题。本地化变量很好。print "\nReturning: " . $thiskey . "\n";
,而是print "\nReturning: $thiskey\n";
,或者如果你不需要第一个\n
:{{1} }(仅限5.10)say "Returning: $thiskey;"
grep
对0 .. $#array;
完全蹩脚,只是grep over the array:grep {} @{$foo[0]}
,而且代码太复杂了,你几乎肯定不希望grep
(虽然我不明白你要做的是说实话。)查看perldoc -q first
- 简而言之 grep直到最后才停止。最后,不要将数组分配给标量:$thiskey = @result;
是隐式$thiskey = scalar @result;
(请参阅perldoc -q scalar
)以获取更多信息。你可能想要的是返回数组引用。这样的事情(消除了$thiskey
)
printf "\nReturning: %s\n", join ', ', @result;
@result ? \@result : 'NULL';
答案 2 :(得分:1)
如果您打算返回是否找到匹配项,则此代码应该有效(低效)。但是,如果您打算返回密钥,则不会 - @result的标量值(当您说$thiskey = @result;
时,这就是您得到的)是列表中的项目数,不是第一个条目。
$thiskey = @result;
应该更改为$thiskey = $result[0];
,如果您希望与基于此功能的代码具有大致相同的功能。请注意,它不再考虑多个匹配,除非您完整地返回@result,无论如何哪种更有意义。