努力したWiki

推敲の足りないメモ書き多数

ユーザ用ツール

サイト用ツール


documents:proglang:perl:perl-014

差分

このページの2つのバージョン間の差分を表示します。

この比較画面へのリンク

両方とも前のリビジョン前のリビジョン
documents:proglang:perl:perl-014 [2026/05/08 11:54] – ↷ documents:perl:perl-014 から documents:proglang:perl:perl-014 へページを移動しました。 k896951documents:proglang:perl:perl-014 [2026/05/17 14:58] (現在) k896951
行 1: 行 1:
 +====== 001.map関数とgrep関数の覚書 ======
  
 +2016/03/27\\
 +ループをゴリゴリ書かないで済ますため雛型用に記録します。
 +
 +===== map関数 =====
 +
 +^ map関数使用例 ^
 +|<code perl map.pl>
 +use strict;
 +
 +my @data = ( 1, 2, 3, 4, 5 );
 +my %hash = ( 1=>"a", 2=>"b", 3=>"c", 4=>"d", 5=>"e" );
 +my @ans1;
 +my @ans2;
 +
 +sub func
 +{
 +  my ($arg) = @_;
 +
 +  return $arg / 2;
 +}
 +
 +  @ans1 = map( $_ * 2   , @data );          ## exsample 1
 +  @ans2 = map( func($_) , @data );          ## exsample 2
 +  map( { $hash{$_}=uc($hash{$_}) } @data ); ## exsample 3
 +
 +  print "ex 1 : " . join(", ", @ans1) . "\n";
 +  print "ex 2 : " . join(", ", @ans2) . "\n";
 +  print "ex 3 : " . join(", ", values(%hash)) . "\n";
 +</code>実行結果<code>
 +$ perl map.pl
 +ex 1 : 2, 4, 6, 8, 10
 +ex 2 : 0.5, 1, 1.5, 2, 2.5
 +ex 3 : B, E, C, A, D
 +$
 +</code>|
 +
 +map関数に与える配列の各要素に計算(ex1, ex2)を行い結果をリストで返します。\\
 +結果がいらないなら各要素毎に何か処理(ex 3)を行わせるためだけに使う事もできます。
 +
 +===== grep関数 =====
 +
 +^ grep関数使用例 ^
 +|<code perl grep.pl>
 +use strict;
 +
 +my @data1 = ( 1, 2, 3, 4, 5, 2, 4, 6 );
 +my @data2 = ( "apple", "orange", "potato", "grape" );
 +my @ans1;
 +my @ans2;
 +my @ans3;
 +my @ans4;
 +
 +sub func
 +{
 +  my ($arg) = @_;
 +
 +  return $arg % 2;
 +}
 +
 +  ## main
 +
 +  @ans1 = grep( $_ % 3   ,  @data1 );                          ## exsample 1
 +  @ans2 = grep( func($_) ,  @data1 );                          ## exsample 2
 +  @ans3 = grep( { 1 if (($_==3)||($_==5)||($_==6)) } @data1 ); ## exsample 3
 +  @ans4 = grep( /[gr]/   ,  @data2 );                          ## exsample 4
 +
 +  print "ex 1 : " . join(", ", @ans1) . "\n";
 +  print "ex 2 : " . join(", ", @ans2) . "\n";
 +  print "ex 3 : " . join(", ", @ans3) . "\n";
 +  print "ex 4 : " . join(", ", @ans4) . "\n";
 +</code>実行結果<code>
 +$ perl grep.pl
 +ex 1 : 1, 2, 4, 5, 2, 4
 +ex 2 : 1, 3, 5
 +ex 3 : 3, 5, 6
 +ex 4 : orange, grape
 +$
 +</code>|
 +
 +grep関数に与える配列の各要素に判定処理(ex1, ex2)を行い結果が真なら要素をリストで返します。\\
 +判定処理は何か処理(ex 3)でも構わないし、配列が文字列であれば正規表現(ex 4)を適用する事もできます。
 +
 +===== map,grep関数応用 =====
 +
 +==== 配列Aの重複要素を排除 ====
 +
 +<code perl samle1.pl>
 +$ cat sample1.pl
 +use strict;
 +
 +my @aryA = ( "radish",     "banana", "orange",
 +             "apple",      "ginger", "banana",
 +             "strawberry", "grape",  "apple" );
 +my $str0;
 +my $str1;
 +
 +  ## 配列A
 +  $str0 = join(", ", @aryA);
 +
 +  ## 配列Aから重複排除
 +  {
 +    my %ans;
 +    map( { $ans{$_}=0 } @aryA );
 +
 +    $str1 = join(", ", keys(%ans) );
 +  }
 +
 +  print "0:$str0\n";
 +  print "1:$str1\n";
 +</code>
 +
 +実行結果
 +<code>
 +$ perl sample1.pl
 +0:radish, banana, orange, apple, ginger, banana, strawberry, grape, apple
 +1:grape, orange, strawberry, banana, radish, apple, ginger
 +$
 +</code>
 +
 +配列Aの要素をハッシュのキーにして重複を消します。map関数をループ処理の代替としています。
 +
 +^ 処理  ^ map関数の時  ^
 +|<code perl>
 +my %ans;
 +foreach ( @aryA )
 +{
 +  $ans{$_}=0;
 +}
 +@ans = keys(%ans);
 +</code>|<code perl>
 +my %ans;
 +map( { $ans{$_}=0 } @aryA );
 +@ans = keys(%ans);
 +</code>|
 +
 +このくらいだとforeachを1行で書いてしまえばいいので微妙かな。
 +
 +==== 配列Bの要素を配列Aから削除 ====
 +
 +<code perl sample2.pl>
 +use strict;
 +
 +my @aryA = ( "radish",     "banana", "orange",
 +             "apple",      "ginger", "banana",
 +             "strawberry", "grape",  "apple" );
 +my @aryB = ( "radish",     "ginger", "potato" );
 +my $str0;
 +my $str1;
 +
 +  ## 配列A
 +  $str0 = join(", ", @aryA);
 +
 +  ## 配列Aから配列Bの要素排除
 +  {
 +    my %ex  =  map(  ($_=>0) ,        @aryB );
 +    my @ans = grep( !exists($ex{$_}), @aryA );
 +
 +    $str1 = join(", ", @ans );
 +  }
 +
 +  print "0:$str0\n";
 +  print "1:$str1\n";
 +</code>
 +
 +実行結果
 +<code>
 +$ perl sample2.pl
 +0:radish, banana, orange, apple, ginger, banana, strawberry, grape, apple
 +1:banana, orange, apple, banana, strawberry, grape, apple
 +$
 +</code>
 +
 +配列Bの要素をハッシュのキーにして、配列Aの要素がハッシュのキーとして存在するか否かで排除有無を判定しています。
 +^ 処理  ^ map,grep関数組み合わせ  ^
 +|<code perl>
 +my %ex;
 +my @ans;
 +foreach (@aryB)
 +{
 +  $ex{$_}=0;
 +}
 +foreach (@aryA)
 +{
 +  if (!exists($ex{$_}))
 +  {
 +    push(@ans, $_);
 +  }
 +}
 +</code>|<code perl>
 +my %ex  =  map(  ($_=>0) ,        @aryB );
 +my @ans = grep( !exists($ex{$_}), @aryA );
 +</code>|
 +
 +まだこのくらいならどちらでも意図は伝わりそう。
 +
 +==== 重複要素と配列Bの要素を配列Aから削除 ====
 +
 +^ map関数  ^ grep関数  ^
 +|<code perl sample3.pl>
 +use strict;
 +
 +my @aryA = ( "radish",     "banana", "orange",
 +             "apple",      "ginger", "banana",
 +             "strawberry", "grape",  "apple" );
 +my @aryB = ( "radish",     "ginger", "potato" );
 +my $str0;
 +my $str1;
 +
 +  ## 配列A
 +  $str0 = join(" , ", @aryA);
 +
 +  ## 配列Aから重複排除後に配列Bの要素を排除
 +  {
 +    my %ans = map( ($_=>0),   @aryA );
 +    map( { delete($ans{$_}) } @aryB );
 +
 +    $str1 = join(" , ", keys(%ans) );
 +  }
 +
 +  print "0:$str0\n";
 +  print "1:$str1\n";
 +</code>|<code perl sample4.pl>
 +use strict;
 +
 +my @aryA = ( "radish",     "banana", "orange",
 +             "apple",      "ginger", "banana",
 +             "strawberry", "grape",  "apple" );
 +my @aryB = ( "radish",     "ginger", "potato" );
 +my $str0;
 +my $str1;
 +
 +  ## 配列A
 +  $str0 = join(" , ", @aryA);
 +
 +  ## 配列Aから重複排除後に配列Bの要素を排除
 +  {
 +    my %wk;
 +    my @ans;
 +    my %ex = map( ($_=>0), @aryB );
 +
 +    @ans = grep( !$wk{$_}++,       @aryA );
 +    @ans = grep( !exists($ex{$_}), @ans  );
 +
 +    $str1 = join(" , ", @ans );
 +  }
 +
 +  print "0:$str0\n";
 +  print "1:$str1\n";
 +</code>|
 +
 +実行結果
 +^ sample3.pl  ^ sample4.pl  ^
 +|<code>
 +$ perl sample3.pl
 +0:radish , banana , orange , apple , ginger , banana , strawberry , grape , apple
 +1:banana , strawberry , apple , grape , orange
 +$
 +</code>|<code>
 +$ perl sample4.pl
 +0:radish , banana , orange , apple , ginger , banana , strawberry , grape , apple
 +1:banana , orange , apple , strawberry , grape
 +$
 +</code>|
 +
 +関数なのに関数として使っていない例ばっかりで……
 +
 +^ 処理  ^ map関数処理  ^ grep関数処理  ^
 +|<code perl>
 +my %ans;
 +foreach ( @aryA)
 +{
 +  $ans{$_}=0;
 +}
 +foreach (@aryB)
 +{
 +  delete($ans{$_});
 +}
 +@ans = keys(%ans);
 +</code>|<code perl>
 +my @ans;
 +my %ans = map( ($_=>0),   @aryA );
 +map( { delete($ans{$_}) } @aryB );
 +@ans = keys(%ans);
 +</code>|<code perl>
 +my %wk;
 +my @ans;
 +my %ex = map( ($_=>0), @aryB );
 +@ans = grep( !$wk{$_}++,       @aryA );
 +@ans = grep( !exists($ex{$_}), @ans  );
 +</code>|
 +
 +map関数+ハッシュの組み合わせでも、grep関数+ハッシュの組み合わせでも実現できます。処理の意味合いによってどちらを使うか考えてみるのが良いかなと思います。
 +grep関数を使う場合は、要素の並びが変わらないので、できるだけ並びを維持したいときはgrep関数が良いかもしれません。
 +
 +{{tag>技術資料 Perl map grep 関数}}
documents/proglang/perl/perl-014.txt · 最終更新: by k896951

Donate Powered by PHP Valid HTML5 Valid CSS Driven by DokuWiki