- ベストアンサー
重複する領域を統合する方法
はじめまして、皆様のお知恵を拝借したく投稿しました。 よろしくお願いします。 perlでのデータ処理で入力ファイルが --------------------------------- start end 1 4 6 10 12 16 14 20 22 25 --------------------------------- となっている場合、4行目の開始位置が3行目の終了位置よりも 前になっているデータがあるとします。 (領域14~16までが領域が重複しているという意味です)。 この重複している領域部分を統合して --------------------------------- start end 1 4 6 10 12 20 22 25 --------------------------------- と再出力できるようにperlでコーディングしたいのですが どのようにしたらよいのでしょうか? ご助言いただけますと幸いです
- みんなの回答 (2)
- 専門家の回答
質問者が選んだベストアンサー
単に「ある区間の開始位置が別の区間の終了位置より前にあったら (適切に) マージする」だけかなぁ? 動いているような気はするけどちょっと不安. あと, 「区間」の考え方によっては変更が必要です. #!/usr/bin/perl my @ranges = ( [1, 4], [6, 10], [12, 16], [14, 20], [22, 25], ); my @results; @ranges = sort { $a->[0] <=> $b->[0] || $a->[1] <=> $b->[1] } @ranges; my $theRange = shift @ranges; for my $range (@ranges) { if ($theRange->[1] < $range->[0]) { push @results, $theRange; $theRange = $range; } elsif ($theRange->[1] < $range->[1]) { $theRange->[1] = $range->[1]; } } push @results, $theRange; for my $range (@results) { print "$range->[0] $range->[1]\n"; }
その他の回答 (1)
- kumoz
- ベストアンサー率64% (120/185)
start と end の中間の数字も1つの配列に入れ、並べ替えて、隣り合う2つの数字を比較して、 差が 2 以上ある場合は、前の数字を範囲の終わり、後の数字を範囲の始まりとして出力しています。 use strict; my @list = (1 .. 4, 6 .. 10, 12 .. 16, 14 .. 20, 22 .. 25); @list = sort { $a <=> $b } @list; print "$list[0] "; my $p = $list[0]; foreach my $n (@list[1 .. $#list]) { print "$p\n$n " if $n - $p >= 2; $p = $n; } print "$list[$#list]\n";
お礼
なるほど、こんなにシンプルにまとめられることもできるんですね。 まったく思いつきませんでした ありがとうございます
お礼
なるほど、二次元配列を使う手があるのは気がつきませんでした。 早速のご回答ありがとうございます。 ご参考の意見を基に早速試してみます。 取り急ぎ御礼まで