Changeset 26873

Show
Ignore:
Timestamp:
12/16/08 19:20:01 (4 years ago)
Author:
drry
Message:
  • fixed an XHTML.
Location:
websites/perl-users.jp
Files:
2 modified

Legend:

Unmodified
Added
Removed
  • websites/perl-users.jp/html/articles/advent-calendar/2008/16.html

    r26870 r26873  
    1313<p>すしを奢らなければいけないなんて、バトンを渡されてから知りました。おいしい寿司が食いたい sekimura です。</p> 
    1414 
    15 <p>今回は使いこなすと気持ちよくて、使いすぎると気持ち悪いと言われてしまう grep と map の使い方について紹介します。この二つは文法がよく似ていて、同時に使われることも多いので一気に両方の使い方を覚えるのをおすすめします。</p> 
     15<p>今回は使いこなすと気持ちよくて、使いすぎると気持ち悪いと言われてしまう <code>grep</code> と <code>map</code> の使い方について紹介します。この二つは文法がよく似ていて、同時に使われることも多いので一気に両方の使い方を覚えるのをおすすめします。</p> 
    1616 
    1717<h2>grep: 配列をフィルターする</h2> 
    1818 
    19 <p>まずは、前回覚えた perldoc を使って grep とはなにかを調べてみましょう。</p> 
     19<p>まずは、前回覚えた perldoc を使って <code>grep</code> とはなにかを調べてみましょう。</p> 
    2020 
    2121<pre><code>$ perldoc -f grep 
     
    3333</code></pre> 
    3434 
    35 <p>「Unix コマンドの grep 等のコマンドと似てるけど違うもの。だって正規表現以外も使えるんだぜ」とか書いていますね。 LIST の全要素を($_ を局所的にセットしながら) BLOCK か EXPR で評価し、その結果が真となるものだけからなる配列を返します。スカラコンテキストの場合は、結果が真となる要素の数を返します。例えば %ENV のキーからなる配列から "H" で始まるものだけを抜き出すには以下のようにします。</p> 
     35<p>「UNIX コマンドの <code>grep</code> 等のコマンドと似てるけど違うもの。だって正規表現以外も使えるんだぜ」とか書いていますね。LIST の全要素を(<code>$_</code> を局所的にセットしながら)BLOCK か <code>EXPR</code> で評価し、その結果が真となるものだけからなる配列を返します。スカラコンテキストの場合は、結果が真となる要素の数を返します。例えば <code>%ENV</code> のキーからなる配列から <code>"H"</code> で始まるものだけを抜き出すには以下のようにします。</p> 
    3636 
    3737<pre><code>$ perl -e 'print join " ", (grep /^H/, keys %ENV), "\n"' 
    38 HOME HISTCONTROL  
     38HOME HISTCONTROL 
    3939</code></pre> 
    4040 
    41 <p>grep は BLOCK を使った場合にもっと楽しくなります。例えば、以下のように、ある二つの配列をつなぎ合わせたものから、重複を取り除いた配列を得ることができます。</p> 
     41<p><code>grep</code> は BLOCK を使った場合にもっと楽しくなります。例えば、以下のように、ある二つの配列をつなぎ合わせたものから、重複を取り除いた配列を得ることができます。</p> 
    4242 
    43 <pre><code> 
    44 my @cities = ('Sapporo', 'Nishitokyo', 'Yokohama'); 
     43<pre><code>my @cities = ('Sapporo', 'Nishitokyo', 'Yokohama'); 
    4544my @prefs  = ('Hokkaido', 'Tokyo', 'Yokohama'); 
    4645my %seen; 
     
    5150</code></pre> 
    5251 
    53 <p>逆に重複したものだけ抜き出したいときには以下のように grep で取得した配列に対して grep することで得られます。</p> 
     52<p>逆に重複したものだけ抜き出したいときには以下のように <code>grep</code> で取得した配列に対して <code>grep</code> することで得られます。</p> 
    5453 
    55 <pre><code> 
    56 my @lunch  = ('Bento', 'Ramen', 'Onigiri', 'Curry'); 
     54<pre><code>my @lunch  = ('Bento', 'Ramen', 'Onigiri', 'Curry'); 
    5755my @dinner = ('Tonkatsu', 'Ramen', 'Curry'); 
    5856my %seen; 
    5957 
    60 my @dup = grep { $seen{$_} >= 2 } grep { ++$seen{$_} > 1 } (@luch, @dinner); 
     58my @dup = grep { $seen{$_} &gt;= 2 } grep { ++$seen{$_} &gt; 1 } (@luch, @dinner); 
    6159 
    6260## @dup には ('Ramen', 'Curry') が入る。 
     
    6563<h2>map: 配列の要素を変換する</h2> 
    6664 
    67 <p>例によって perldoc -f map しましょう。</p> 
     65<p>例によって <code>perldoc -f map</code> しましょう。</p> 
    6866 
    6967<pre><code>$ perldoc -f map 
     
    7876</code></pre> 
    7977 
    80 <p>ほとんど同じことが書いてありますね。grep はフィルターなので、得られる配列は与えられた配列のサブセットになるのに対して、 map では与えられた各要素を変換し、その結果を配列として得ることが可能です。</p> 
     78<p>ほとんど同じことが書いてありますね。<code>grep</code> はフィルターなので、得られる配列は与えられた配列のサブセットになるのに対して、<code>map</code> では与えられた各要素を変換し、その結果を配列として得ることが可能です。</p> 
    8179 
    82 <pre><code> 
    83 my %price_map = ( 
    84   'Ramen' => 400, 
    85   'Curry' => 650, 
    86   'Katsudon' => 600, 
     80<pre><code>my %price_map = ( 
     81  'Ramen' =&gt; 400, 
     82  'Curry' =&gt; 650, 
     83  'Katsudon' =&gt; 600, 
    8784); 
    8885my @today = ('Ramen', 'Curry'); 
     
    9491</code></pre> 
    9592 
    96 <p>grep のときにはスルーしましたが、 BLOCK 内での $_ は元の要素のリファレンスなので、 $_ を変更してしまうと、元の要素も変更されてしまいます。よく、「破壊的」と呼ばれるケースですね。これを防ぐには、 BLOCK の内部で my 変数にコピーしてから変更を加えていきます。</p> 
     93<p><code>grep</code> のときにはスルーしましたが、 BLOCK 内での <code>$_</code> は元の要素のリファレンスなので、<code>$_</code> を変更してしまうと、元の要素も変更されてしまいます。よく、「破壊的」と呼ばれるケースですね。これを防ぐには、 BLOCK の内部で <code>my</code> 変数にコピーしてから変更を加えていきます。</p> 
    9794 
    98 <pre><code> 
    99 my @addresses = ('katsuo@example.com', 'wakame@example.com', 'tara@example.com'); 
     95<pre><code>my @addresses = ('katsuo@example.com', 'wakame@example.com', 'tara@example.com'); 
    10096my @no_spam = map { my $email = $_; $email =~ s/\@/ at /; $email } @addresses; 
    101 </code></pre> 
    10297 
    10398## @no_spam には ('katsuo at example.com', 'wakame at example.com', 'tara at example.com) が入る。 
    10499</code></pre> 
    105100 
    106 <p>このようにして、 @addresses の要素を変更すること無く @no_spam という変換後の要素を持つ配列を得ることができます。</p> 
     101<p>このようにして、<code>@addresses</code> の要素を変更すること無く <code>@no_spam</code> という変換後の要素を持つ配列を得ることができます。</p> 
    107102 
    108103<h2>使いどころ</h2> 
    109 <p>grep, map 両方共 for, foreach のループで書き換えることができますが、それぞれ「フィルター」と「変換」という意味をコードを読む人に的確に伝えることができるのがメリットではないでしょうか。その他にも、デバッガーやワンライナーでループ処理を簡素に書けるのも利点です。 sort 等のコマンドと組み合わせて Unix のパイプのようにデータを処理すると自分が偉くなったような錯覚に陥るのがオススメどころです。 
     104<p><code>grep</code>, <code>map</code> 両方共 <code>for</code>, <code>foreach</code> のループで書き換えることができますが、それぞれ「フィルター」と「変換」という意味をコードを読む人に的確に伝えることができるのがメリットではないでしょうか。その他にも、デバッガーやワンライナーでループ処理を簡素に書けるのも利点です。 <code>sort</code> 等のコマンドと組み合わせて UNIX のパイプのようにデータを処理すると自分が偉くなったような錯覚に陥るのがオススメどころです。 
    110105</p> 
    111 <p>ただし、 grep, map を単にループ処理をするために、左辺値を受け取らずに使うのはコードを読む人を混乱させるので避けた方がいいでしょう。 (SEE ALSO perldoc perlstyle) 
     106<p>ただし、 <code>grep</code>, <code>map</code> を単にループ処理をするために、左辺値を受け取らずに使うのはコードを読む人を混乱させるので避けた方がいいでしょう。 (SEE ALSO <code>perldoc perlstyle</code>) 
    112107</p> 
    113108 
  • websites/perl-users.jp/ttroot/articles/advent-calendar/2008/16.html

    r26870 r26873  
    1414<p>すしを奢らなければいけないなんて、バトンを渡されてから知りました。おいしい寿司が食いたい sekimura です。</p> 
    1515 
    16 <p>今回は使いこなすと気持ちよくて、使いすぎると気持ち悪いと言われてしまう grep と map の使い方について紹介します。この二つは文法がよく似ていて、同時に使われることも多いので一気に両方の使い方を覚えるのをおすすめします。</p> 
     16<p>今回は使いこなすと気持ちよくて、使いすぎると気持ち悪いと言われてしまう <code>grep</code> と <code>map</code> の使い方について紹介します。この二つは文法がよく似ていて、同時に使われることも多いので一気に両方の使い方を覚えるのをおすすめします。</p> 
    1717 
    1818<h2>grep: 配列をフィルターする</h2> 
    1919 
    20 <p>まずは、前回覚えた perldoc を使って grep とはなにかを調べてみましょう。</p> 
     20<p>まずは、前回覚えた perldoc を使って <code>grep</code> とはなにかを調べてみましょう。</p> 
    2121 
    2222<pre><code>$ perldoc -f grep 
     
    3434</code></pre> 
    3535 
    36 <p>「Unix コマンドの grep 等のコマンドと似てるけど違うもの。だって正規表現以外も使えるんだぜ」とか書いていますね。 LIST の全要素を($_ を局所的にセットしながら) BLOCK か EXPR で評価し、その結果が真となるものだけからなる配列を返します。スカラコンテキストの場合は、結果が真となる要素の数を返します。例えば %ENV のキーからなる配列から "H" で始まるものだけを抜き出すには以下のようにします。</p> 
     36<p>「UNIX コマンドの <code>grep</code> 等のコマンドと似てるけど違うもの。だって正規表現以外も使えるんだぜ」とか書いていますね。LIST の全要素を(<code>$_</code> を局所的にセットしながら)BLOCK か <code>EXPR</code> で評価し、その結果が真となるものだけからなる配列を返します。スカラコンテキストの場合は、結果が真となる要素の数を返します。例えば <code>%ENV</code> のキーからなる配列から <code>"H"</code> で始まるものだけを抜き出すには以下のようにします。</p> 
    3737 
    3838<pre><code>$ perl -e 'print join " ", (grep /^H/, keys %ENV), "\n"' 
    39 HOME HISTCONTROL  
     39HOME HISTCONTROL 
    4040</code></pre> 
    4141 
    42 <p>grep は BLOCK を使った場合にもっと楽しくなります。例えば、以下のように、ある二つの配列をつなぎ合わせたものから、重複を取り除いた配列を得ることができます。</p> 
     42<p><code>grep</code> は BLOCK を使った場合にもっと楽しくなります。例えば、以下のように、ある二つの配列をつなぎ合わせたものから、重複を取り除いた配列を得ることができます。</p> 
    4343 
    44 <pre><code> 
    45 my @cities = ('Sapporo', 'Nishitokyo', 'Yokohama'); 
     44<pre><code>my @cities = ('Sapporo', 'Nishitokyo', 'Yokohama'); 
    4645my @prefs  = ('Hokkaido', 'Tokyo', 'Yokohama'); 
    4746my %seen; 
     
    5251</code></pre> 
    5352 
    54 <p>逆に重複したものだけ抜き出したいときには以下のように grep で取得した配列に対して grep することで得られます。</p> 
     53<p>逆に重複したものだけ抜き出したいときには以下のように <code>grep</code> で取得した配列に対して <code>grep</code> することで得られます。</p> 
    5554 
    56 <pre><code> 
    57 my @lunch  = ('Bento', 'Ramen', 'Onigiri', 'Curry'); 
     55<pre><code>my @lunch  = ('Bento', 'Ramen', 'Onigiri', 'Curry'); 
    5856my @dinner = ('Tonkatsu', 'Ramen', 'Curry'); 
    5957my %seen; 
    6058 
    61 my @dup = grep { $seen{$_} >= 2 } grep { ++$seen{$_} > 1 } (@luch, @dinner); 
     59my @dup = grep { $seen{$_} &gt;= 2 } grep { ++$seen{$_} &gt; 1 } (@luch, @dinner); 
    6260 
    6361## @dup には ('Ramen', 'Curry') が入る。 
     
    6664<h2>map: 配列の要素を変換する</h2> 
    6765 
    68 <p>例によって perldoc -f map しましょう。</p> 
     66<p>例によって <code>perldoc -f map</code> しましょう。</p> 
    6967 
    7068<pre><code>$ perldoc -f map 
     
    7977</code></pre> 
    8078 
    81 <p>ほとんど同じことが書いてありますね。grep はフィルターなので、得られる配列は与えられた配列のサブセットになるのに対して、 map では与えられた各要素を変換し、その結果を配列として得ることが可能です。</p> 
     79<p>ほとんど同じことが書いてありますね。<code>grep</code> はフィルターなので、得られる配列は与えられた配列のサブセットになるのに対して、<code>map</code> では与えられた各要素を変換し、その結果を配列として得ることが可能です。</p> 
    8280 
    83 <pre><code> 
    84 my %price_map = ( 
    85   'Ramen' => 400, 
    86   'Curry' => 650, 
    87   'Katsudon' => 600, 
     81<pre><code>my %price_map = ( 
     82  'Ramen' =&gt; 400, 
     83  'Curry' =&gt; 650, 
     84  'Katsudon' =&gt; 600, 
    8885); 
    8986my @today = ('Ramen', 'Curry'); 
     
    9592</code></pre> 
    9693 
    97 <p>grep のときにはスルーしましたが、 BLOCK 内での $_ は元の要素のリファレンスなので、 $_ を変更してしまうと、元の要素も変更されてしまいます。よく、「破壊的」と呼ばれるケースですね。これを防ぐには、 BLOCK の内部で my 変数にコピーしてから変更を加えていきます。</p> 
     94<p><code>grep</code> のときにはスルーしましたが、 BLOCK 内での <code>$_</code> は元の要素のリファレンスなので、<code>$_</code> を変更してしまうと、元の要素も変更されてしまいます。よく、「破壊的」と呼ばれるケースですね。これを防ぐには、 BLOCK の内部で <code>my</code> 変数にコピーしてから変更を加えていきます。</p> 
    9895 
    99 <pre><code> 
    100 my @addresses = ('katsuo@example.com', 'wakame@example.com', 'tara@example.com'); 
     96<pre><code>my @addresses = ('katsuo@example.com', 'wakame@example.com', 'tara@example.com'); 
    10197my @no_spam = map { my $email = $_; $email =~ s/\@/ at /; $email } @addresses; 
    102 </code></pre> 
    10398 
    10499## @no_spam には ('katsuo at example.com', 'wakame at example.com', 'tara at example.com) が入る。 
    105100</code></pre> 
    106101 
    107 <p>このようにして、 @addresses の要素を変更すること無く @no_spam という変換後の要素を持つ配列を得ることができます。</p> 
     102<p>このようにして、<code>@addresses</code> の要素を変更すること無く <code>@no_spam</code> という変換後の要素を持つ配列を得ることができます。</p> 
    108103 
    109104<h2>使いどころ</h2> 
    110 <p>grep, map 両方共 for, foreach のループで書き換えることができますが、それぞれ「フィルター」と「変換」という意味をコードを読む人に的確に伝えることができるのがメリットではないでしょうか。その他にも、デバッガーやワンライナーでループ処理を簡素に書けるのも利点です。 sort 等のコマンドと組み合わせて Unix のパイプのようにデータを処理すると自分が偉くなったような錯覚に陥るのがオススメどころです。 
     105<p><code>grep</code>, <code>map</code> 両方共 <code>for</code>, <code>foreach</code> のループで書き換えることができますが、それぞれ「フィルター」と「変換」という意味をコードを読む人に的確に伝えることができるのがメリットではないでしょうか。その他にも、デバッガーやワンライナーでループ処理を簡素に書けるのも利点です。 <code>sort</code> 等のコマンドと組み合わせて UNIX のパイプのようにデータを処理すると自分が偉くなったような錯覚に陥るのがオススメどころです。 
    111106</p> 
    112 <p>ただし、 grep, map を単にループ処理をするために、左辺値を受け取らずに使うのはコードを読む人を混乱させるので避けた方がいいでしょう。 (SEE ALSO perldoc perlstyle) 
     107<p>ただし、 <code>grep</code>, <code>map</code> を単にループ処理をするために、左辺値を受け取らずに使うのはコードを読む人を混乱させるので避けた方がいいでしょう。 (SEE ALSO <code>perldoc perlstyle</code>) 
    113108</p> 
    114109