perlの比較、ループの使い方について質問です。
perlの初心者でperlを使っていろいろと勉強しているのですが、以下のような場合、簡単に書ける方法ってないでしょうか?
比較、ループなど調べてみたのですが、なかなか思うようにいきません。
よろしくお願いします。
なお、以下のスクリプトではエラーが出て動きませんが、その点は今回の説明の為ご了承願います。
my @hoge(1,10,100,1000,10000,100000,1000000);
my $no=☆ ←☆については1~5の間でランダムに設定します。
my(@test);
for (my $i=0; $i<$no; $i++) {
@test[$i]=@hoge[$i];
}
例えば$noが2の場合、@test[0]と@test[1]を比較(@test[0]<@test[1])して偽の場合は、エラーを出し、$noが3の場合、@test[0]と@test[1]と@test[2]を比較(@test[0]<@test[1]<@test[2])して偽の場合は、エラーを出し、$noが4の場合、@test[0]と@test[1]と@test[2]と@test[3]を比較(@test[0]<@test[1]<@test[2]<@test[3])して偽の場合は、エラーを出し……以下同じような感じで進めたいのですが、簡単な書き方ってないでしょうか?
if ($no==2){
unlss (@test[0]<@test[1]){エラー}
}elsif($no==3){
unless (@test[0]<@test[1]<@test[2]){エラー}
}elsif($no==4){
unless (@test[0]<@test[1]<@test[2]<@test[3]){エラー}
}
上記のような書き方となるかと思いますが、$noが2の場合、test配列に@test[2]と@test[3]が変数としてない為上記の書き方ではスクリプト自体エラーとなります。
説明が分かりにくい点については申し訳ありませんが、どなたかご教授願えないでしょうか。
よろしくお願いします。
No.1
- 回答日時:
配列の要素を使用するときは
$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]);
}
のような感じかぁとは思うのですが、ここからどのように比較し真、偽を判別していくかがよく分かりません。
もしよろしければ、簡単にで結構ですので、ループから比較の書き方を教えていただけないでしょうか。
よろしくお願いいたします。
No.2
- 回答日時:
文法的なことは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を繰り返さない(一般に,同じことの繰り返しはしない方がいい)
・処理を細切れにして(一個の処理単位はできるだけ短く),
入口と出口を明確にして,それらをつなぎ合わせる
というようなことです.
具体的なコードはご自分でどうぞ.
「スライス」「ソート」「配列の比較」という
よくある処理の組み合わせです.
No.3ベストアンサー
- 回答日時:
配列の要素が数値順に並んでいるか否かのチェックは 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 {
# 数値順に並んでいないときの処理
}
丁寧にご教授いただきありがとうございます。
初心者な者で、理解に時間がかかりましたがようやく分かってきました。
ありがとうございました。
No.4
- 回答日時:
> my $hoge = (1, 10, 100, 50, 1000, 10000, 5000, 100000);
No3 です。すみませんが、1つ記述ミスがありました。以下のように訂正します。
my @hoge = (1, 10, 100, 50, 1000, 10000, 5000, 100000);
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
似たような質問が見つかりました
- Mac OS PATHを使ってcdなどで簡単に移動できるようになりたい 3 2023/05/13 14:22
- C言語・C++・C# 質問です 下記のコードを分かりやすく解説お願いします 初心者です #include ‹stdio.h 3 2022/05/26 22:03
- その他(プログラミング・Web制作) VScodeでpythonプログラムの関数を実行したい 2 2022/07/13 19:24
- PHP $_SESSIONについて教えて下さい。 2 2023/03/02 09:18
- Access(アクセス) MAXで0が出力される 1 2022/03/31 21:43
- PHP PHP一覧表示した項目にリンクをはりたい 1 2023/07/12 17:08
- Excel(エクセル) VBA ワークシート指定の1行目を選択をしたい 2 2022/08/20 18:10
- サーバー Windowsサーバでグループを検索したい 1 2023/04/17 15:30
- JavaScript [再掲]指定したパスが現URLに含まれていたら特定要素を削除するJavascriptのコードについて 1 2023/05/10 15:09
- Excel(エクセル) Excelの置換が上手くいかない Microsoft® Excel® 2019 MSO (バージョン 5 2022/08/17 22:26
関連するカテゴリからQ&Aを探す
おすすめ情報
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
Can't use string ("0") as an ...
-
プログラミングについて。 1つ...
-
画面を強制的に再描画させる方法
-
VBのReturnの使い方
-
DoEventsが必要な理由について
-
クラスに配列を渡す方法
-
pythonでファイルのコメント行...
-
DOSコマンドのループ内のTIMEコ...
-
For文を使った九九表の作成
-
VBAで3秒だけ時間を止めたい
-
英語でのシャープとコメの呼び...
-
vbscriptでIE自動入力(途中で...
-
ループ内での条件処理
-
CSVファイルの特定の行だけを読...
-
GIFアニメをループさせたくない
-
VBA横データを縦にしたいです
-
vb.netからエクセル関数書き込み
-
VBScript 配列
-
エクセル関数で1〜12の数字がル...
-
vb.netです。2次元配列の要素を...
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
Can't use string ("0") as an ...
-
行指向処理でデータの読み込み...
-
サンプルの意味
-
画面を強制的に再描画させる方法
-
VBAで3秒だけ時間を止めたい
-
VBAでの一時停止と再開の方法
-
VBのReturnの使い方
-
どなたかこのプログラミングを...
-
Escキーを押すと、中断する時と...
-
UWSCの終了の仕方
-
エクセルの当番表を作っていま...
-
VBA for i=1 to lastrow
-
「偶数・奇数の和」のフローチ...
-
VBAのautofilter、criteriaの配...
-
アクティブセルから、A列最終行...
-
DoEventsが必要な理由について
-
vb.netからエクセル関数書き込み
-
GIFアニメをループさせたくない
-
DOSコマンドのループ内のTIMEコ...
-
ハッシュ検索はなぜ速い
おすすめ情報