• ベストアンサー
※ ChatGPTを利用し、要約された質問です(原文:[Perl]長すぎるif文を簡単にしたい)

[Perl]長すぎるif文を簡単にしたい

このQ&Aのポイント
  • Perlのプログラムで、同じ値が続く場合にその値を出力する方法について、より短いif文を作りたいです。現在のif文は長くなってしまい、スッキリとしたコードにしたいです。
  • 現在のコードは&&を使用して値が5回連続して同じ場合に出力するようになっています。しかし、連続した値が50回や100回になると条件式がとても長くなり、変更が難しくなってしまいます。より短いif文の書き方があれば教えてください。
  • プログラムで連続した値を判定する際に、現在は&&を連結して値を比較していますが、よりシンプルな方法があれば知りたいです。変数とループを組み合わせて、長いif文を避ける方法があれば教えてください。

質問者が選んだベストアンサー

  • ベストアンサー
  • JaneDue
  • ベストアンサー率75% (263/350)
回答No.4

Perlはちょっとうろ覚えですが、単に取り出すだけなら文字列のまま取得してもいいかも。 ------------------ $N= 5; $n=$N-1; @arr; while ( $str =~ m/(([\d\.]+) [\d\.]+ [\d\.]+\n(?:\2 [\d\.]+ [\d\.]+\n){$n,})/og ){ push(@arr,$&); } #確認 print "<pre>"; foreach $var (@arr) { print "$var<hr>"; } print "</pre>"; ------------------ ~以上ではなく、厳密にN回なら カンマなしで{$n}

すると、全ての回答が全文表示されます。

その他の回答 (6)

回答No.7

再帰呼び出しで比較、カウンタ変数で連続回数を判定すればいいような気がします。 #!/usr/bin/perl use strict; use warnings; use feature qw/say switch/; use utf8; use open IO => qw/:utf8 :std/; my @list = <DATA>; # 比較する数値が入ったリスト my @kaburi = (); # 繰り返しの数値が入るリスト my $count = 0; # カウンタ変数 sub yobidasi { my $num = shift @_; $count++; yobidasi(shift @list) if defined $list[0] && $num eq $list[0]; push @kaburi, $num if $count > 1; # ここの数値で連続回数を指定 $count = 0; } while (my $num = shift @list) { yobidasi($num); } say @kaburi; __DATA__ 0.00 2.0 11.5 0.01 6.3 17.2 0.01 2.1 14.2 0.01 1.2 14.3 0.01 2.1 14.3 0.01 3.7 14.3 0.01 3.7 14.3 0.01 4.1 14.3 0.06 4.1 14.3 0.01 4.1 14.9 0.01 4.1 14.9 0.01 4.1 14.9 0.01 4.1 14.9 0.01 4.1 14.9 0.01 4.1 14.9 0.01 4.1 14.9 0.01 4.1 14.9 0.01 4.1 14.9 0.01 4.1 14.9 0.03 4.1 14.8 で、出力はこんな感じなると思います。 0.01 3.7 14.3 0.01 4.1 14.9 比較の条件がよくわからなかったので、行単位での文字列比較で再帰呼び出しを行っています。ここはsplit使うなりして、お好きなように設定してみてください。

Lena_River
質問者

お礼

お礼が遅くなり申し訳ありませんでした。 内容を理解するまで少し時間をいただけないでしょうか。 丁寧にご回答をしていただき、ありがとうございました。 何とか頑張ってみます。

すると、全ての回答が全文表示されます。
  • JaneDue
  • ベストアンサー率75% (263/350)
回答No.6

ぐだぐたで悪い。Ano3ではなくAno4の書き落としです。

Lena_River
質問者

お礼

お礼が遅くなってしまい、申し訳ありませんでした。 プログラム内容について、私には少し難易度が高くて頭の中でグルグル回っています。 消化するまで少しお時間をください! 丁寧にお答えいただき、本当にありがとうございました。

すると、全ての回答が全文表示されます。
  • JaneDue
  • ベストアンサー率75% (263/350)
回答No.5

Ano3 書き落としすみません。$strは文字列のままのデータ全部です。 $str = " # ヘッダー 0.00 2.0 11.5 0.01 6.3 17.2 0.01 2.1 14.2 0.01 1.2 14.3 0.01 2.1 14.3 0.01 3.7 14.3 0.01 3.7 14.3 0.01 4.1 14.3 0.06 4.1 14.3 0.01 4.1 14.9 0.01 4.1 14.9 0.03 4.1 14.8 ";

すると、全ての回答が全文表示されます。
  • poppo64
  • ベストアンサー率57% (11/19)
回答No.3

こんな感じでしょうか。 指定回数を $limen に入れることで柔軟に繰り返し回数の条件を変更できます。 「同じ値が〇回続く」を if 文で判定するのではなく、内側のループ INNER_LOOP で現時点から1つづつカウンタを進めて1回1回判定していくようにしています。 値が同じであれば繰り返されているので、繰り返している回数を $reptation に増加していきます。 カウンタが指定回数まで達すると、条件を満たしたことを $is_recured に代入します。 外側のループ OUTER_LOOP の最後で $is_recured が真なら出力します。 出力の際はあらかじめ記録しておいた $repatation を使い、繰り返している回数分だけ出力します。 以下、例示します。 字下げに全角空白を用いてますのでコピペして試す場合は適宜削除して実行してください。 use strict; my $data = <<'EOD'; #ヘッダー 0.00 2.0 11.5 0.01 6.3 17.2 0.01 2.1 14.2 0.01 1.2 14.3 0.01 2.1 14.3 0.01 3.7 14.3 0.01 3.7 14.3 0.01 4.1 14.3 0.06 4.1 14.3 0.01 4.1 14.9 0.01 4.1 14.9 0.03 4.1 14.8 EOD # テキストデータを分割して各配列に入れる my( @A, @B, @C ); foreach my $item ( split /\n/, $data ){   next if $item =~ /^#/ ;   my ($value_a, $value_b, $value_c ) = split / /, $item;   push @A, 0+$value_a;   push @B, 0+$value_b;   push @C, 0+$value_c; } my $limen = 5; # 条件となる繰り返し回数 my $array_length = @A; # @A の要素数 OUTER_LOOP: for( my $idx = 0; $idx < $array_length; $idx++ ){   my $is_recured; # 繰り返し回数を満たしたかどうかを記憶する変数   my $reptation = 1; # 繰り返された回数。1回は必ず繰り返すので初期値は1   # 配列の最後まで次々と比較するループ   INNER_LOOP:   for( my $fore = 1; $idx + $fore < $array_length; $fore++ ){     # 値が同じなら繰り返し回数を増加     if( $A[ $idx ] == $A[ $idx + $fore ] ){       $reptation += 1;     }     # 値が異なればこのループを抜ける     else {       last;     }     # 条件回数に達したらフラグをセット     if( $reptation == $limen ){       $is_recured = 1;     }   }   # フラグが立っていれば、指定回数同じ値が続いているので出力   if( $is_recured ){     print "repeat same value $reptation times.\n";     for( my $i = 0; $i < $reptation; $i++ ){       print "$A[$idx+$i], $B[$idx+$i], $C[$idx+$i]\n";     }     print "----------------------\n";   } } __END__ 実行結果 repeat same value 7 times. 0.01, 6.3, 17.2 0.01, 2.1, 14.2 0.01, 1.2, 14.3 0.01, 2.1, 14.3 0.01, 3.7, 14.3 0.01, 3.7, 14.3 0.01, 4.1, 14.3 ---------------------- repeat same value 6 times. 0.01, 2.1, 14.2 0.01, 1.2, 14.3 0.01, 2.1, 14.3 0.01, 3.7, 14.3 0.01, 3.7, 14.3 0.01, 4.1, 14.3 ---------------------- repeat same value 5 times. 0.01, 1.2, 14.3 0.01, 2.1, 14.3 0.01, 3.7, 14.3 0.01, 3.7, 14.3 0.01, 4.1, 14.3 ----------------------

Lena_River
質問者

お礼

丁寧に回答していただき有り難うございました。 こ、こんなに長くなってしまうんですね。 頑張って参考にさせていただきます。 有り難うございました!

すると、全ての回答が全文表示されます。
  • Tacosan
  • ベストアンサー率23% (3656/15482)
回答No.2

「ある値がどれだけ連続しているか」を数えればいいんだけど.... なんで @A[$i] なんだろう. $A[$i] にしない理由が思いつかない.

Lena_River
質問者

補足

すみません、実際のプログラムとデータはもっと複雑なので@A[$i]にしていました。 質問内容を省き過ぎて申し訳ありませんでした。 if文の条件式を簡略化したいのです。 現段階では「指定した回数分」を "&&"を繰り返し使用していて 非効率的なので困っています。 ご回答ありがとうございました。

すると、全ての回答が全文表示されます。
  • gtx456gtx
  • ベストアンサー率18% (194/1035)
回答No.1

ifで判定するのではなく配列に格納し全てのデータを読み取ったら、配列を確認するという処理をしては?

Lena_River
質問者

お礼

すみません、それができなくて苦労しています。 ご回答、ありがとうございました。

すると、全ての回答が全文表示されます。

関連するQ&A