2012-06-14 3 views
0

При использовании следующих данных:Perl: Сравнение номеров в строке

A | 11 162 60 90 - 141 184

B | 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; 

Я не знаю, сколько элементов в каждой строке. Поэтому я не знаю, как реализовать цикл для сравнения. Любые рекомендации по улучшению кода будут оценены.

Благодарим за помощь.

ответ

1

Во-первых, я хотел бы изменить пару вещей о сценарии. 1) использовать строгое - это будет означать, что вы поймаете какие-либо опечатки

2) дать переменные более значимые имена - я изменил некоторые, которые имеют смысл, основываясь на том, что я видел, но я не знаю, что делает ваш скрипт , так что вы можете иметь лучшие из них

3) Выход некоторые отладки, в то время как вы развиваете его, так что вы можете увидеть, что он делает и почему он не работает

Вам понадобятся две петли - один к перебрать значения в части строки слева от «-» и одну, чтобы перебрать условия с правой стороны. Вы хотите перебрать значения во внешнем цикле, а затем каждый раз через это вы должны пересечь ВСЕ условия во внутреннем цикле.

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"; 

       } 
     } 
} 

Примечание - Я оставил строку отладки там

+0

Эй, спасибо большое. Оно работает. – zock

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 
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 
Смежные вопросы