2010-06-13 59 views
2

我正在从之前发布的问题(here)开始工作,并试图将答案转换为子版本,以便多次使用它。不确定它是否正确。任何人都可以提供更好或更清洁的子?将代码转换为Perl子版,但不知道我是否正确

我有很多编程经验,但我的主要语言是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' 
}); 

---编辑---

从到目前为止的答案,我下面的功能拼凑起来。我是新的 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}; 
} 
+2

您缺少'use strict;使用警告;'在脚本/模块的顶部。它会捕获许多错误并使诊断程序更有用(当您的示例代码中已经修复了这些简单错误时,它们更有可能为SO上的人员提供帮助)。 – Ether 2010-06-13 17:13:43

+0

@Ether ...此代码是来自较大脚本的复制粘贴。我在完整的脚本中使用严格和警告。 – 2010-06-13 17:30:18

+1

'foreach $ row(@ {$ args - > {search_ary}}){'说你没有。或者,你忽略了你所得到的错误,这同样糟糕。 – Ether 2010-06-13 17:47:09

回答

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

如果你打算返回是否找到匹配,该代码应工作(低效率)。如果您打算返回密钥,但它不会 - @result的标量值(这就是您在说$thiskey = @result;时得到的)是列表中项目的数量,而不是第一个项目。

$thiskey = @result;可能应该更改为$thiskey = $result[0];,如果您希望大部分功能等同于您基于此的代码。请注意,它不会再考虑多个匹配,除非您完整地返回@result,这无论如何都会更有意义。

4

这整个小组真的很混乱,我是一个相当普通的perl用户。以下是一些全面的建议。

  • 不要创建自己的undef不断 - 使用undef然后在底部return $var // 'NULL'返回。
  • 千万不要这样做:foreach $row,因为foreach my $row不太容易产生问题。本地化变量是很好的。
  • 不要无谓地串连,因为它冒犯了上帝风格:不是这个,print "\nReturning: " . $thiskey . "\n";,但print "\nReturning: $thiskey\n";,或者如果你不需要第一\nsay "Returning: $thiskey;"(5.10只)
  • grep荷兰国际集团在0 .. $#array;是断然瘸子,只是grep整个数组:grep {} @{$foo[0]},并且该代码是如此复杂,你几乎肯定不想grep(虽然我不明白你在做什么诚实。)。退房​​- 总之grep不会停止,直到结束

最后,不要一个数组赋值给一个标量:$thiskey = @result;一个隐含的$thiskey = scalar @result;(见perldoc -q scalar)获取更多信息。你可能想要的是返回数组引用。像这样的东西(其消除$thiskey

printf "\nReturning: %s\n", join ', ', @result; 
@result ? \@result : 'NULL'; 
+0

伟大的建议,++。但是,请注意潜在的误导性词汇表:“本地化变量很好”。在“编程”方面,这是非常好的建议。在“Perl编程”的语境中,你的陈述是误导性的,因为它可以被理解为意味着词法和动态范围是等价的。 “本地”和“本地化”这个令人讨厌的事实在Perl中具有特定的含义,与普通的本地化的comp sci含义不同的是“限制范围”。如何将句子改为“最小化变量的范围很好”。或类似的东西? – daotoad 2010-06-14 06:27:24

+0

我宁愿使用[正确的术语](http://en.wikipedia.org/wiki/Local_variable)而不是perl特定的工作,以避免使用相当少使用的变量声明'local'的内涵。 – 2010-06-14 16:51:56

相关问题