2010-07-28 4 views
0

У меня есть 2 файла. Один файл - это данные, которые обновляются каждые 10 минут, а вторая - данные, которые ранее использовались. То, что я пытаюсь сделать, это взять одну строку из нового файла и пропустить через каждую строку второго файла и посмотреть, соответствует ли она одному. Если это так, я не хочу его использовать, но если нет совпадения, я хочу добавить его в строку. В том, что я сделал до сих пор, кажется, что проверка никогда не набирает совпадения, даже если она есть. Вот то, что у меня есть, и образец данных, которые я использовал из обоих файлов. CHECKHAIL и USEDHAIL являются двумя файламиLooping через файлы с perl

while(my $toBeChecked = <CHECKHAIL>){ 
     my $found = 0; 
     seek USEDHAIL, 0, 0 or die "$0: seek: $!"; 
     while(my $hailCheck = <USEDHAIL>){ 
      if($toBeChecked == $hailCheck){ 
       $found += 1; 
      } 
     } 
     print USEDHAIL $toBeChecked; 
     if ($found == 0){ 
      $toEmail .= $toBeChecked; 
     } 
    } 
    print $toEmail; 
    return; 
} 

CHECKHAIL выборочные данные

2226 175 2 NE  LAWRENCE   DEADWOOD   SD 44.4 -103.7 (UNR) 

2305 200 2 S  SISKIYOU   GREENVIEW  CA 41.52 -122.9 2 INCH HAIL REPORTED WITH STORM JUST SOUTH OF GREENVIEW. (MFR) 

2350 200    DANIELS   E FLAXVILLE  MT 48.8 -105.17 GOLF BALL TO HEN EGG SIZED HAIL (GGW) 

2350 175 5 N  DANIELS   RICHLAND   MT 48.89 -106.05 DESTROYED CROPS (GGW) 

USEDHAIL выборочные данные

2226 175 2 NE  LAWRENCE   DEADWOOD   SD 44.4 -103.7 (UNR) 

2305 200 2 S  SISKIYOU   GREENVIEW  CA 41.52 -122.9 2 INCH HAIL REPORTED WITH STORM JUST SOUTH OF GREENVIEW. (MFR) 
+0

Это звучит неплохо, а сложность задачи - O (n ** 2). Просто поместите данные в базу данных, добавьте ограничение первичного ключа на то, что определяет его как UNIQUE, добавьте еще один столбец «date_entered DEFAULTS CURRENT_TIMESTAMP», а затем SELECT, где «date_entered> TODAY -« 1 день »:: interval'. –

ответ

2

Почему бы вам просто не создать хэш для первого (использованного) файла?

use strict; 
use warnings; 
my %fromUsedFile; 
open USEDFILE, '<', '/the/data/file/that/is/10minutesold'; 
$fromUsedFile{$_}++ while <USEDFILE>; 
close USEDFILE; 

while ($toBeChecked = <CHECKHAIL>) { 
    if (defined $fromUsedFile{$toBeChecked}) { 
     # ... line is in both the new and old file 
    } else { 
     # ... line is only in the new file 
     $toBeEmailed .= $toBeChecked; 
    } 
} 
+0

Потому что я не знаю, как создать хэш. Я попробую это, хотя – shinjuo

+0

это дает мне синтаксические ошибки для $ usedFileName и $ fromUSedFile. Какую декларацию я должен сделать с этими – shinjuo

+0

@shinjuo - ответьте на обновления, чтобы работать больше из коробки с включенным 'strict'. – mob

1

Использование $ _ в пределах внутреннего контура может вызвать проблемы. Попробуйте сначала называть свои строки следующим образом:

while(my $toBeChecked = <CHECKHAIL>){ 
    my $found = 0; 
    while(my $hailCheck = <USEDHAIL>){ 

Также perl видит сравнение чисел и сравнение строк по-разному. Вы используете сравнение строк вместо числового сравнения:

if ($found eq 0){ 

Изменение к:

if ($found == 0){ 
+0

Это очень полезно знать, но я все еще получаю ту же проблему. – shinjuo

+1

см. Редактирование. Я только что разместил – Cfreak

+0

. Я не знал, что либо все еще не работает – shinjuo

1

Эта линия торчит для меня:

if ($found eq 0){ 

Поскольку $found является логическим, выполнить логическое испытания на нем:

if (not $found) { 

Это также похоже на то, что ваша логика немного изменилась - в первом if вы возвращаетесь, если строки не соответствуют, а затем во втором if, вы возвращаетесь, если была совпадение. Возможно, вы намерены сказать next;, чтобы пропустить из самого внутреннего цикла?

+0

Все еще не работает. Вы хотели сделать, если ($ found) { , а затем поместите конкатенацию в} else {part? То, что я пробовал – shinjuo

+0

Мне даже не нужен первый на самом деле, я просто хочу проверить, является ли это совпадением. – shinjuo

3

Он никогда не имеет возможности для достижения успеха из-за

while(<USEDHAIL>){ 
    my $hailCheck = $_; 
    if($toBeChecked eq $hailCheck){ 
     $found += 1; 
    }else{ 
     return; ### XXX 
    } 
} 

На первом рассогласования, суб возвращается к абоненту. Возможно, вы имели в виду next, но для краткости вы должны удалить весь пункт else. Удалите другой else { return; } (соответствует тому, когда $found верно) по той же причине.

Обратите внимание, что ваш алгоритм имеет квадратичную сложность и будет медленным для больших входов. Было бы лучше прочитать использованные записи в хеш, а затем для каждой строки CHECKHAIL проконсультироваться с хешем %used, чтобы узнать, обработано ли оно.

С этими линиями удалены, я получаю

$ ./prog.pl 

2305 200 2 S  SISKIYOU   GREENVIEW  CA 41.52 -122.9 2 INCH HAIL REPORTED WITH STORM JUST SOUTH OF GREENVIEW. (MFR) 

2350 200    DANIELS   E FLAXVILLE  MT 48.8 -105.17 GOLF BALL TO HEN EGG SIZED HAIL (GGW) 

2350 175 5 N  DANIELS   RICHLAND   MT 48.89 -106.05 DESTROYED CROPS (GGW)

Как вы можете видеть, что все еще есть ошибка.Вам нужно перемотать USEDHAIL для каждой строки CHECKHAIL:

seek USEDHAIL, 0, 0 or die "$0: seek: $!"; 
while(<USEDHAIL>){ 
... 

Это производит

$ ./prog.pl 
2350 200    DANIELS   E FLAXVILLE  MT 48.8 -105.17 GOLF BALL TO HEN EGG SIZED HAIL (GGW) 
2350 175 5 N  DANIELS   RICHLAND   MT 48.89 -106.05 DESTROYED CROPS (GGW)

Для примера лучшего способа сделать это, рассмотрим

#! /usr/bin/perl 

use warnings; 
use strict; 

sub read_used_hail { 
    my($path) = @_; 

    my %used; 

    open my $fh, "<", $path or die "$0: open $path: $!"; 

    local $" = " "; # " fix Stack Overflow highlighting 
    while (<$fh>) { 
    chomp; 
    my @f = split " ", $_, 10; 
    next unless @f; 
    ++$used{"@f"}; 
    } 

    wantarray ? %used : \%used; 
} 

my %used = read_used_hail "used-hail"; 
open my $check, "<", "check-hail" or die "$0: open: $!"; 

while (<$check>) { 
    chomp; 
    my @f = split " ", $_, 10; 
    next if [email protected] || $used{join " " => @f}; 
    print $_, "\n"; 
} 

Sample пробег:

$ ./prog.pl 
2350 200    DANIELS   E FLAXVILLE  MT 48.8 -105.17 GOLF BALL TO HEN EGG SIZED HAIL (GGW) 
2350 175 5 N  DANIELS   RICHLAND   MT 48.89 -106.05 DESTROYED CROPS (GGW)
+0

Где бы я помещал мои пути к файлу в этом. Я довольно новичок в perl, если вы не можете сказать, и некоторые из этих вещей я никогда не использовал. – shinjuo

+0

Код выше hardcodes - это невообразимые имена 'check-hail' и' used-hail' для двух входных файлов. –

+0

Редактированный код, который я использовал выше, является тем, что я пробовал, и он не работал. Теперь я попытаюсь работать с тем, что вы только что дали мне, и посмотреть, что это. – shinjuo