- ベストアンサー
Perlの比較、ループの使い方について質問
- Perlの比較、ループの使い方について質問です。perlの初心者でperlを使っていろいろと勉強しているのですが、簡単に書ける方法はないでしょうか?
- 質問者はPerl初心者であり、比較やループの方法について簡単な書き方を知りたいと述べています。具体的な要件として、指定された数値の配列要素を比較し、条件に合わない場合にエラーを出力したいとのことです。
- さらに、現在のコードではエラーが出力されず、正常な動作ができていないと報告しています。この問題の解決策も求められています。
- みんなの回答 (4)
- 専門家の回答
質問者が選んだベストアンサー
配列の要素が数値順に並んでいるか否かのチェックは grep を使って行うことができます。次のコードは、すべての隣接する要素を数値比較し、直前の要素よりも小さい要素の添字を @small に入れるものです。 my $hoge = (1, 10, 100, 50, 1000, 10000, 5000, 100000); my @small = grep { $hoge[$_ - 1] > $hoge[$_] } 1 .. $#hoge; print "$hoge[$_ -1] > $hoge[$_]\n" foreach @small; 範囲演算子の両側の数値を変えれば、部分配列もチェックできます。1 .. 3 とすれば先頭の4つを、3 .. 5 とすれば添字 2 から 5 までをチェックできます。また、grep は if や unless 条件部に置くことができます。次のコードは、$hoge[0] < $hoge[1] < $hoge[2] と同等の効果が得られます。 unless (grep { $hoge[$_ - 1] >= $hoge[$_] } 1 .. 2) { # 数値順に並んでいるときの処理 } else { # 数値順に並んでいないときの処理 }
その他の回答 (3)
- kumoz
- ベストアンサー率64% (120/185)
> my $hoge = (1, 10, 100, 50, 1000, 10000, 5000, 100000); No3 です。すみませんが、1つ記述ミスがありました。以下のように訂正します。 my @hoge = (1, 10, 100, 50, 1000, 10000, 5000, 100000);
- kabaokaba
- ベストアンサー率51% (724/1416)
文法的なことはNo.1さんのご指摘の通りですが・・・・ たぶんきちんとした書籍を読んだ方がいいです. ぜったいこんな書き方しない!っていう書き方が散見できますので #my(@test) なんて普通は書かない・・・ #意図的にわざとすることがないとは言わないけど 次に,きちんと処理手順を考えましょう 要は $no の値に応じて,異なるものを比較して結果を出したいということでしょう $no=2 => $test[0]<$test[1] $no=3 => $test[0]<$test[1]<$test[2] という具合に($no=1の場合のチェックは?). となると, (1) $noに応じて,比較対象を取り出す (2) 取り出した比較対象を実際に比較する (1)については配列の「スライス」をすればいいでしょう. 配列@testの0..$no-1の要素を取り出せばOK (2)については@testの各要素が数字であるという条件で 今回のように「順番」であることを求めるならば ソートを使えばいいでしょう. @testの0..$no-1でできた配列の要素と,それを昇順で並べた配列の要素が 順番も含めて完全に一致していればクリア,そうでなければアウト #この処理だと$noのときは常にクリアとなる ついでにいえば,質問に書かれていることだけなら @hogeからわざわざ@testをコピーする必要はないでしょう? @hogeをそのまま使えばOKでは? アルゴリズムの一例をあげました. こういうののコツは ・if-elseを繰り返さない(一般に,同じことの繰り返しはしない方がいい) ・処理を細切れにして(一個の処理単位はできるだけ短く), 入口と出口を明確にして,それらをつなぎ合わせる というようなことです. 具体的なコードはご自分でどうぞ. 「スライス」「ソート」「配列の比較」という よくある処理の組み合わせです.
- kmee
- ベストアンサー率55% (1857/3366)
配列の要素を使用するときは $test[0] と$を使うのが普通。 @test[0]は 0番目の要素からなるリスト。 この違いは場合によっては結構重要。 > $test[0]<$test[1]<$test[2] Perlではこのような条件式の書き方はゆるされていません。 このような数学的な書き方は、プログラミング言語によって 1)そもそも文法エラーになる 2)書けるけど実行時にエラー 3)書けるけど意味が違う: a<b<c→a<bの真偽を表す値と cの比較(真偽が1/0なら 1<c または 0<c) 4)数学と同じ意味 となり、Perlでは1)、C言語では3)で、4)という言語はほとんどありません。 syntax error at XXX.pl line XX, near "] <" とかいうエラーメッセージではなかったですか?(こちらではそうなりました) これは「文法(syntax)間違い(error)」です。 >@test[2]と@test[3]が変数としてない為 のエラーではありません。そもそもPerlでは、使用してない添字を指定してもエラーは出ません。 a<b<c → a<b かつ b<c という意味を明確に指定する必要があります ($test[0]<$test[1]) && ($test[1]<$test[2]) こう分けて考えれば ($test[0]<$test[1]) ($test[1]<$test[2]) ... ($test[i-1]<$test[i]) .... ($test[n-1-1]<$test[n-1]) となることがわかります。これは、ループを使って簡単に書くことができます。
補足
早速ありがとうございます。 >配列の要素を使用するときは >$test[0] と$を使うのが普通。 >@test[0]は 0番目の要素からなるリスト。 >この違いは場合によっては結構重要。 @を使っても$を使っても同じ事だと思ってたので、普通に@を使ってましたが…。 今後は$を使うようにします。 >$test[0]<$test[1]<$test[3] こちらが文法エラーだったとは…。勉強不足です。 教えていただきありがとうございます。 >a<b<c → a<b かつ b<c >という意味を明確に指定する必要があります >($test[0]<$test[1]) && ($test[1]<$test[2]) >こう分けて考えれば >($test[0]<$test[1]) >($test[1]<$test[2]) >... >($test[i-1]<$test[i]) >.... >($test[n-1-1]<$test[n-1]) >となることがわかります。これは、ループを使って簡単に書くことができます。 ($test[i-1]<$test[i])までは分かるのですが(例えば私が示した$i=2の場合, $test[1]<$test[2]となる)、($test[n-1-1]<$test[n-1])のnとはどのような場合なのでしょうか。 またループについてですが、 for (1..3){ ($test[i-1]<$test[i]); } のような感じかぁとは思うのですが、ここからどのように比較し真、偽を判別していくかがよく分かりません。 もしよろしければ、簡単にで結構ですので、ループから比較の書き方を教えていただけないでしょうか。 よろしくお願いいたします。
お礼
丁寧にご教授いただきありがとうございます。 初心者な者で、理解に時間がかかりましたがようやく分かってきました。 ありがとうございました。