254 lines
12 KiB
Markdown
254 lines
12 KiB
Markdown
---
|
||
title: '『新版Perl言語プログラミングレッスン入門編』第6章: 繰り返し'
|
||
author: kazu634
|
||
date: 2008-02-06
|
||
url: /2008/02/06/_839/
|
||
wordtwit_post_info:
|
||
- 'O:8:"stdClass":13:{s:6:"manual";b:0;s:11:"tweet_times";i:1;s:5:"delay";i:0;s:7:"enabled";i:1;s:10:"separation";s:2:"60";s:7:"version";s:3:"3.7";s:14:"tweet_template";b:0;s:6:"status";i:2;s:6:"result";a:0:{}s:13:"tweet_counter";i:2;s:13:"tweet_log_ids";a:1:{i:0;i:3691;}s:9:"hash_tags";a:0:{}s:8:"accounts";a:1:{i:0;s:7:"kazu634";}}'
|
||
categories:
|
||
- Perl
|
||
- Programming
|
||
|
||
---
|
||
<div class="section">
|
||
<p>
|
||
繰り返しについて勉強するよー
|
||
</p>
|
||
|
||
<p>
|
||
<a name="seemore"></a>
|
||
</p>
|
||
|
||
<h4>
|
||
foreach構文
|
||
</h4>
|
||
|
||
<p>
|
||
これまで何度も出てきた構文。変数の中にリストの値を順番に格納する構文だよ。基本構造は
|
||
</p>
|
||
|
||
<pre class="syntax-highlight">
|
||
<span class="synStatement">foreach</span> <span class="synStatement">my</span> 変数 (リスト) {
|
||
処理
|
||
}
|
||
</pre>
|
||
|
||
<p>
|
||
というようになる。「my 変数」は省略可能で、処理の中で「$_」と表記できる。例はこんな感じ:
|
||
</p>
|
||
|
||
<pre class="syntax-highlight">
|
||
<span class="synStatement">use strict</span>;
|
||
<span class="synStatement">use warnings</span>;
|
||
<span class="synStatement">my</span> <span class="synIdentifier">@name</span> = (<span class="synConstant">'Musashi'</span>, <span class="synConstant">'Aiko'</span>, <span class="synConstant">'Nanbu'</span>);
|
||
<span class="synStatement">foreach</span> (<span class="synIdentifier">@name</span>) {
|
||
<span class="synStatement">print</span> <span class="synConstant">"</span><span class="synIdentifier">$_</span><span class="synSpecial">\n</span><span class="synConstant">"</span>;
|
||
}
|
||
</pre>
|
||
|
||
<p>
|
||
リストの値でソートさせて表示させたいときにはこのようにする。
|
||
</p>
|
||
|
||
<pre class="syntax-highlight">
|
||
<span class="synStatement">use strict</span>;
|
||
<span class="synStatement">use warnings</span>;
|
||
<span class="synStatement">my</span> <span class="synIdentifier">@name</span> = (<span class="synConstant">'Musashi'</span>, <span class="synConstant">'Aiko'</span>, <span class="synConstant">'Nanbu'</span>);
|
||
<span class="synStatement">foreach</span> (<span class="synStatement">sort</span>(<span class="synIdentifier">@name</span>)) {
|
||
<span class="synStatement">print</span> <span class="synConstant">"</span><span class="synIdentifier">$_</span><span class="synSpecial">\n</span><span class="synConstant">"</span>;
|
||
}
|
||
</pre>
|
||
|
||
<p>
|
||
逆順にソートするときは「reverse(sort(@name))」とすればいい。reverseは「リストの内容を単純に逆にするだけ」ということに注意。だから「reverse(@name)」は
|
||
</p>
|
||
|
||
<ol>
|
||
<li>
|
||
Nanbu
|
||
</li>
|
||
<li>
|
||
Aiko
|
||
</li>
|
||
<li>
|
||
Musashi
|
||
</li>
|
||
</ol>
|
||
|
||
<p>
|
||
という結果になるよ!当たり前だけど、foreachを二重(orそれ以上)にすることもできる。例としてはこんなのが載っていた:
|
||
</p>
|
||
|
||
<pre class="syntax-highlight">
|
||
<span class="synStatement">use strict</span>;
|
||
<span class="synStatement">use warnings</span>;
|
||
<span class="synStatement">my</span> <span class="synIdentifier">@data</span> = (
|
||
<span class="synConstant">"Musashi, 70, 83, 41"</span>,
|
||
<span class="synConstant">"Aiko, 90, 70, 50"</span>,
|
||
<span class="synConstant">"Nanbu,100, 30, 20"</span>,
|
||
);
|
||
<span class="synStatement">foreach</span> (<span class="synIdentifier">@data</span>) {
|
||
<span class="synStatement">my</span> (<span class="synIdentifier">$name</span>, <span class="synIdentifier">@score</span>) = <span class="synStatement">split</span>(<span class="synStatement">/</span><span class="synConstant">,</span><span class="synStatement">/</span>, <span class="synIdentifier">$_</span>);
|
||
<span class="synStatement">my</span> <span class="synIdentifier">$sum</span> = <span class="synConstant"></span>;
|
||
<span class="synStatement">foreach</span> (<span class="synIdentifier">@score</span>) {
|
||
<span class="synIdentifier">$sum</span> += <span class="synIdentifier">$_</span>;
|
||
}
|
||
<span class="synStatement">print</span> <span class="synConstant">"</span><span class="synIdentifier">$name</span><span class="synConstant">: </span><span class="synIdentifier">$sum</span><span class="synSpecial">\n</span><span class="synConstant">"</span>;
|
||
}
|
||
</pre>
|
||
|
||
<p>
|
||
自分としては「my ($name, @score) = split(/,/, $_);」がファジーすぎると感じる。説明によれば、
|
||
</p>
|
||
|
||
<blockquote>
|
||
<p>
|
||
split(/,/, $line)は、$lineの文字列をコンマで区切り、そのそれぞれの要素をまとめたリストを作ります。例えば、$lineの値が
|
||
</p>
|
||
|
||
<pre class="syntax-highlight">
|
||
<span class="synConstant">'Hiroshi Yuki, 70, 83, 41'</span>
|
||
</pre>
|
||
|
||
<p>
|
||
だとすると、split(/,/, $line)の値は、
|
||
</p>
|
||
|
||
<pre class="syntax-highlight">
|
||
(<span class="synConstant">'Hiroshi Yuki'</span>, <span class="synConstant">'70'</span>, <span class="synConstant">'83'</span>, <span class="synConstant">'41'</span>)
|
||
</pre>
|
||
|
||
<p>
|
||
というリストになります。代入する先の左辺は、($name, @score)というリストになっているので、
|
||
</p>
|
||
|
||
<pre class="syntax-highlight">
|
||
<span class="synStatement">my</span> <span class="synIdentifier">$name</span> = <span class="synConstant">'Hiroshi Yuki'</span>;
|
||
<span class="synStatement">my</span> <span class="synIdentifier">@score</span> = (<span class="synConstant">'70'</span>, <span class="synConstant">'83'</span>, <span class="synConstant">'41'</span>);
|
||
</pre>
|
||
|
||
<p>
|
||
と同じことになります。
|
||
</p>
|
||
</blockquote>
|
||
|
||
<p>
|
||
「同じことになる」で済ませられているけど、なんかかなりファジーな気がするんですが。。。でも、直感的と言えば直感的かもしれない。要は「最初のヤツだけ$nameに格納、後は@scoreにまとめちゃって」ということなんだろう。
|
||
</p>
|
||
|
||
<p>
|
||
foreach構文の使い道は他にもあって、「ファイルの各行を読み込む」時にも使うよ。例はこんな感じになる。
|
||
</p>
|
||
|
||
<pre class="syntax-highlight">
|
||
<span class="synStatement">use strict</span>;
|
||
<span class="synStatement">use warnings</span>;
|
||
<span class="synStatement">open</span> (<span class="synIdentifier">FILE</span>, <span class="synConstant">'file.txt'</span>) <span class="synStatement">or</span> <span class="synStatement">die</span> <span class="synConstant">"</span><span class="synIdentifier">$!</span><span class="synConstant">"</span>;
|
||
<span class="synStatement">foreach</span> (<span class="synIdentifier"><FILE></span>) {
|
||
<span class="synStatement">print</span> <span class="synIdentifier">$_</span>;
|
||
}
|
||
<span class="synStatement">close</span> (<span class="synIdentifier">FILE</span>);
|
||
</pre>
|
||
|
||
<p>
|
||
説明にはこんな事書いてあったよ!
|
||
</p>
|
||
|
||
<blockquote>
|
||
<p>
|
||
「リスト」のところには<FILE>と書いてあります。Perlではリストを書くべきところに<FILE>と書くと、FILEというファイルハンドルからすべての行をメモリ上に読み込み、その各行を要素とするリストを作成します。これはPerlの約束です。
|
||
</p>
|
||
</blockquote>
|
||
|
||
<p>
|
||
他にも「ディレクトリ内部の各ファイルの繰り返し」にも使えるよ!
|
||
</p>
|
||
|
||
<pre class="syntax-highlight">
|
||
<span class="synStatement">use strict</span>;
|
||
<span class="synStatement">use warnings</span>;
|
||
<span class="synStatement">opendir</span> (<span class="synIdentifier">DIR</span>, <span class="synConstant">'.'</span>) <span class="synStatement">or</span> <span class="synStatement">die</span> <span class="synConstant">"</span><span class="synIdentifier">$!</span><span class="synConstant">"</span>;
|
||
<span class="synStatement">foreach</span> (<span class="synStatement">readdir</span>(<span class="synIdentifier">DIR</span>)) {
|
||
<span class="synStatement">print</span> <span class="synConstant">"</span><span class="synIdentifier">$_</span><span class="synSpecial">\n</span><span class="synConstant">"</span>;
|
||
}
|
||
<span class="synStatement">closedir</span> (<span class="synIdentifier">DIR</span>);
|
||
</pre>
|
||
|
||
<p>
|
||
この前の章でもやったけど、「keysを使うとハッシュを表示できる」よ♪
|
||
</p>
|
||
|
||
<pre class="syntax-highlight">
|
||
<span class="synStatement">use strict</span>;
|
||
<span class="synStatement">use warnings</span>;
|
||
<span class="synStatement">my</span> <span class="synIdentifier">%hash</span> = (
|
||
<span class="synConstant">'Kazu'</span> => <span class="synConstant">10</span>,
|
||
<span class="synConstant">'Yukari'</span> => <span class="synConstant">20</span>,
|
||
<span class="synConstant">'Aiko'</span> => <span class="synConstant">30</span>,
|
||
<span class="synConstant">'Nanbu'</span> => <span class="synConstant">40</span>,
|
||
);
|
||
<span class="synStatement">foreach</span> (<span class="synStatement">keys</span>(<span class="synIdentifier">%hash</span>)) {
|
||
<span class="synStatement">print</span> <span class="synConstant">"</span><span class="synIdentifier">$_</span><span class="synConstant">: </span><span class="synIdentifier">$hash</span><span class="synConstant">{</span><span class="synIdentifier">$_</span><span class="synConstant">}</span><span class="synSpecial">\n</span><span class="synConstant">"</span>;
|
||
}
|
||
</pre>
|
||
|
||
<p>
|
||
「keys(%hash)」で「(‘Kazu’, ‘Yukari’, ‘Aiko’, ‘Nanbu’)」というリストが得られるよ!なにげに「”$_: $hash{$_}\n”;」を「”$_: %hash{$_}\n”」としてしまい、ややはまる。抜けているなー。
|
||
</p>
|
||
|
||
<h4>
|
||
whileを使った繰り返し
|
||
</h4>
|
||
|
||
<p>
|
||
whileの処理はこんな感じになっている:
|
||
</p>
|
||
|
||
<pre class="syntax-highlight">
|
||
<span class="synStatement">while</span> (条件式) {
|
||
繰り返す処理
|
||
}
|
||
</pre>
|
||
|
||
<p>
|
||
条件式が満たされている間中はずっと繰り返し処理を行う。例はこんな感じ。
|
||
</p>
|
||
|
||
<pre class="syntax-highlight">
|
||
<span class="synStatement">use strict</span>;
|
||
<span class="synStatement">use warnings</span>;
|
||
<span class="synStatement">open</span> (<span class="synIdentifier">FILE</span>, <span class="synConstant">'temp.txt'</span>) <span class="synStatement">or</span> <span class="synStatement">die</span> <span class="synConstant">"</span><span class="synIdentifier">$!</span><span class="synConstant">"</span>
|
||
<span class="synStatement">while</span> (<span class="synStatement">my</span> <span class="synIdentifier">$line</span> = <span class="synIdentifier"><FILE></span>) {
|
||
<span class="synStatement">print</span> <span class="synIdentifier">$line</span>;
|
||
}
|
||
<span class="synStatement">close</span>(<span class="synIdentifier">FILE</span>);
|
||
</pre>
|
||
|
||
<p>
|
||
これを別な書き方にもできる。
|
||
</p>
|
||
|
||
<pre class="syntax-highlight">
|
||
<span class="synStatement">use strict</span>;
|
||
<span class="synStatement">use warnings</span>;
|
||
<span class="synStatement">open</span> (<span class="synIdentifier">FILE</span>, <span class="synConstant">'temp.txt'</span>) <span class="synStatement">or</span> <span class="synStatement">die</span> <span class="synConstant">"</span><span class="synIdentifier">$!</span><span class="synConstant">"</span>
|
||
<span class="synStatement">while</span> (<span class="synIdentifier"><FILE></span>) {
|
||
<span class="synStatement">print</span> <span class="synIdentifier">$_</span>;
|
||
}
|
||
<span class="synStatement">close</span>(<span class="synIdentifier">FILE</span>);
|
||
</pre>
|
||
|
||
<p>
|
||
この「$_」の使い方も少し不思議だけど、説明によると:
|
||
</p>
|
||
|
||
<blockquote>
|
||
<p>
|
||
whileの中で<FILE>を使うと、読んだ行の内容がデフォルト変数$_に代入されます。
|
||
</p>
|
||
</blockquote>
|
||
|
||
<p>
|
||
というわけで、お約束らしい。
|
||
</p>
|
||
</div> |