0

次の入力があるとします。

あ| 11 162 60 90 -- 141 184

ビ| 231 322 -- 306 305 285 350

A の場合、141 が (11,162) または (60,90) の間にあるかどうかを確認します。はいの場合、「A では、141 は (11,162) の間にある」と出力します。

次に、184 が (11,162) または (60,90) の間にあるかどうかを確認します。そうではないので、何も印刷する必要はありません。

同様に、B については、(231, 322) の間にある数値を出力する必要があります。

次の Perl コードを書きましたが、正しい出力が得られません。

#!/usr/bin/perl -w
open LIST, "input.txt";
while($line=<LIST>)
{
@elem=split (/\|/,$line);
@nextone=split("--",$elem[1]);
@nextoneone = split(" ",$nextone[0]);
@nexttwo=split(" ",$nextone[1]);

if ($nexttwo[0] > $nextoneone[0] && $nexttwo[0] < $nextoneone[1])
{
print"$elem[0]\t $nexttwo[0]\t $nextoneone[0]\t $nextoneone[1]\n";
}
elsif ($nexttwo[0] > $nextoneone[2] && $nexttwo[0] < $nextoneone[3])
{
print"$elem[0]\t $nexttwo[0]\t $nextoneone[2]\t $nextoneone[3]\n";
}
elsif ($nexttwo[1] > $nextoneone[0] && $nexttwo[1] < $nextoneone[1])
{
print"$elem[0]\t $nexttwo[1]\t $nextoneone[0] \t$nextoneone[1]\n";
}
elsif ($nexttwo[1] > $nextoneone[2] && $nexttwo[1] < $nextoneone[3])
{
print"$elem[0]\t $nexttwo[1]\t $nextoneone[2] \t$nextoneone[3]\n";
}
}
   close (LIST);
   exit;

各行にいくつの要素があるかわかりません。したがって、比較のためのループを実装する方法がわかりません。コードを改善する方法についてのガイダンスをいただければ幸いです。

ご協力ありがとうございました。

4

3 に答える 3

1

まず、スクリプトについていくつか変更します。1) 厳格な使用 - タイプミスをキャッチすることを意味します

2) 変数にもっと意味のある名前を付けます - 私が見たものに基づいて意味のあるものをいくつか変更しましたが、あなたのスクリプトが何をするのかわかりません。

3)開発中にデバッグを出力して、何をしているのか、なぜ機能しないのかを確認できます

2 つのループが必要になります。1 つは文字列の「--」の左側の部分の値をループするためのもので、もう 1 つは右側の条件をループするためのものです。外側のループの値をループし、そのたびに内側のループのすべての条件をループする必要があります。

    use strict;
    #!/usr/bin/perl -w
    open LIST, "input.txt";
    my $line;
    while($line=<LIST>) {
        my ($label, $content) =split (/\|/,$line);
        my ($conditionstring, $valuestring) =split("--",$content);
        my (@conditions) = split(" ",$conditionstring);
        my (@values) =split(" ",$valuestring);
        foreach my $this_val (@values) {
                my $matched_one_condition = 0;
                for (my  $f=0; $f< scalar(@conditions);$f+=2) {


                        print "Comparing $this_val to $conditions[$f] and to            $conditions[$f+1]\n";

                        if (($this_val > $conditions[$f]) && ($this_val < $conditions[$f+1])) {
                                $matched_one_condition= 1;

                        }
                }
                if ($matched_one_condition) {
                        print "$this_val\n";

                }
        }
}

注 - そこにデバッグ行を残しました

于 2012-06-14T11:57:45.707 に答える
0

私はあなたの問題を強打しました。うまくいけば、あなたはそれにいくつかの価値を見つけるでしょう。行Bの場合(306、305など)を処理するために、範囲を自由に並べ替えました。

#!/bin/env perl
use strict;
use warnings;

while ( <DATA> ) {
    my @line = /\w+|\d+/g;
    my( $h, $ranges, $tests ) = (
        $line[0], [ [ sort @line[1,2] ], [ sort @line[3,4] ] ], [ @line[5,6] ]
    );
    map {
        my $test = $_;
        map {
            print "In $h, $test lies between (", join( ', ', @$_ ), ")\n"
                if grep { /^$test$/ } ( $_->[0] .. $_->[1] )
        } ( @$ranges )
    } @$tests
}

__DATA__
A| 11 162 60 90 -- 141 184
B| 231 322 -- 306 305 285 350
于 2012-06-14T14:06:39.553 に答える
0

数値がわからない場合は、値に対してループを使用します。

#!/usr/bin/perl
use warnings;
use strict;
use feature 'say';

while (<DATA>) {
    my ($header, $rangeS, $pointS) = /(.*)\|(.*) -- (.*)/;
    my @ranges = $rangeS =~ /([^ ]+ [^ ]+)/g;
    my @points = split / /, $pointS;

    for my $point (@points) {
        for my $range (@ranges) {
            my ($from, $to) = split / /, $range;
            if ($from <= $point and $point <= $to) {
                say "In $header, $point lies between ($from,$to)";
                last;   # Comment this line to get all the ranges for each point.
            }
        }
    }
}

__DATA__
A| 11 162 60 90 -- 141 184
B| 231 322 -- 306 305 285 350
C| 10 20 30 40 -- 1 2 3 4 5 6 7 8 9
D| 10 20 10 40 -- 1 10 20 40 10
于 2012-06-14T11:57:01.573 に答える