2010-06-13 62 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

相關問題