2

map少し前に、を使ってどのように実装するかという「奇妙な」質問をされましたgrep。今日私はそれをやろうとしました、そしてここに出てきたものがあります。私はPerlからすべてを絞り出しましたか、それとも他にもっと巧妙なハックがありますか?

#!/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);
4

3 に答える 3

11

grepで実装する方法を彼らが尋ねなかったのは確かmapですか?それは実際に時々役に立ちます。

grep { STMTs; EXPR } LIST

次のように書くことができます

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

(1つの違いがあります:grep左辺値を返しますが、返しmapません。)

これを知っていると、コンパクトにできます

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

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

(私は「非圧縮」バージョンの方が好きですが、「圧縮」バージョンの方がおそらく少し高速です。)


mapを使用して実装する場合は、のループとエイリアシングのプロパティgrepを利用できます。grep

map { STMTs; EXPR } LIST

次のように書くことができます

my @rv;
grep { STMTs; push @rv, EXPR } LIST;
@rv
于 2012-06-25T15:26:24.753 に答える
3

このほとんど無意味な学術演習での私の試みはです。

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

マップのリターンリストは入力リストと1:1ではない可能性があるため、これに使用grepするのは少し無駄my %hash = map { $_ => 1 } @array;です。たとえば、grepのリターンリストを使用するよりも一般的である必要があります。その結果、元のリストを変更できる任意の検索方法が機能します。

sub my_map (&@) {
    my $code = shift;
    my @return_list;
    push @return_list, $code->($_) for @_;
    return @return_list;
}
于 2012-06-25T15:13:49.923 に答える
1

mapあなたが何を意味するのか(エミュレートされるのはどのような側面か)は完全にはわかりませんgrepが、典型的なマップシナリオは次のようになりますy = x**3

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

を使用すると、必要に応じて、ほぼ次のように見せることgrepができます(ただし、元のリストを破棄します)。map

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

元のリスト要素の参照に書き込むだけです。ここでの問題は、元のリストの不要な変更です。これはあなたがしたくないことですmap

したがって、サブルーチンで別のリストを生成し、これを変更して、元のリストを変更しないでおくことができます。SinanÜnürのソリューションを少し変更すると、次のようになります。

  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

于 2012-06-25T15:45:37.100 に答える