2012-06-25 57 views
1

前段時間,我被問到「奇怪」的問題,我將如何實施mapgrep。 今天我試圖做到這一點,這是什麼出來。我是否擠壓了Perl的所有內容,或者還有其他更聰明的黑客?在Perl中,如何使用grep實現地圖?

#!/usr/bin/env perl 
use strict; 
use warnings; 
use 5.010; 

sub my_map(&@) { 
    grep { $_= $_[0]->($_) } @_[1..$#_]; 
} 

my @arr = (1,2,3,4); 

#list context 
say (my_map sub {$_+1}, @arr); 
#scalar context 
say "".my_map {$_+1} @arr; 
say "the array from outside: @arr"; 
say "builtin map:", (map {$_+1} @arr); 

回答

10

你確定他們沒有問如何實現grepmap?有時候這實際上很有用。

grep { STMTs; EXPR } LIST 

可以寫成

map { STMTs; EXPR ? $_ :() } LIST 

(有一個區別:grep返回左值,和map不)

知道了這一點,一個可以壓縮

map { $_ => 1 } grep { defined } @list 

map { defined ? $_ => 1 :() } @list 

(我更喜歡「解壓縮」版本,但「壓縮」的版本可能是一個快一點。)


至於使用grep實施map,好了,你可以利用grep優勢循環和混疊屬性。

map { STMTs; EXPR } LIST 

可以寫成

my @rv; 
grep { STMTs; push @rv, EXPR } LIST; 
@rv 
+0

說實話,我現在不知道,就像你說的,可能是。我從來沒有想過爲了好玩而做任何兩個練習。問題的關鍵很可能是看看我對Perl有多熟悉。 –

3

我對這個毫無意義的學術活動的嘗試是。

sub my_map (&@) { 
    my $code = shift; 
    my @return_list; 
    grep { 
     push @return_list, $code->($_); 
    } @_; 
    return @return_list; 
} 

使用grep因爲這是一個有點浪費,因爲地圖的迴歸所列內容可能並不爲1:1的輸入列表,如my %hash = map { $_ => 1 } @array;,你需要更通用,使用返回列表grep的。結果是任何可以修改原始列表的方法都可以工作。

sub my_map (&@) { 
    my $code = shift; 
    my @return_list; 
    push @return_list, $code->($_) for @_; 
    return @return_list; 
} 
1

我不完全明白你的意思(由grep效仿哪些方面map IST),但典型的地圖場景可能是如y = x**3:通過簡單地寫的引用

... 
    my @list2 = grep { $_**=3; 1 } @list1; 
    ... 

... 
    my @list1 = (1,2,3,4,5); 
    my @list2 = map $_**3, @list1; 
    ... 

隨着grep,如果你要,你可以幾乎使其looke像map(但破壞原有的列表)原始列表元素。 問題是原始列表的不需要的修改;這是你不想用map做什麼。

因此,我們可以在子例程中生成另一個列表,修改這個列表並保留原始列表不變。在Sinan Ünür's solution輕微的修改,這將是:

sub gap(&@) { 
    my $code = shift; 
    my @list = @_; 
    grep $_ = $code->($_), @list; 
    @list 
    } 

    my @arr = (1 .. 5); 

    # original map 
    print join ',', map { $_**3 } @arr; 
    # 1,8,27,64,125 

    # grep map 
    print join ',', gap { $_**3 } @arr; 
    # 1,8,27,64,125 

    # test original array 
    print join ',', @arr; 
    # 1,2,3,4,5 => untouched 

問候

RBO

+1

'$ {\ $ _}'與'$ _'相同。你也有一個優先問題。固定。 – ikegami

+0

@ikegami - 謝謝,你是對的。我甚至沒有意識到可以像'map'那樣修改源列表。 –