2012-06-25 20 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'那样修改源列表。 –