Проблема, касающаяся сравнения строк и ссылок в Perl - PullRequest
0 голосов
/ 10 мая 2011

Вот с чего я начну. Я читаю массивы из базы данных по одному, используя цикл while. Я хочу забрать элементы из базы данных, которые являются дубликатами (в определенных полях). Я хочу оставить только те элементы, которые уникальны для этих полей. Затем я хочу распечатать данные, которые я хранил определенным образом. Я создал код, который, как я думал, сделает это, но он дает мне все, включая элементы, которые являются дубликатами на поле. Я искал и искал, и я не могу понять это, я думаю, как Perl Noob, я упускаю что-то простое. Код выглядит следующим образом:

my @uniques = ();
my $output;

while (my @itemArray = $sth->fetchrow_array() ) {
    my $duplicateFlag = 0;  
    foreach (@uniques){
        if(  ($itemArray[3] eq "$_->[3]") and ($itemArray[4] eq "$_->[4]")
               and ($itemArray[5] eq "$_->[5]" ) and ($itemArray[6] eq "$_->[6]" )
               and ($itemArray[7] eq "$_->[7]" ) and ($itemArray[8] == "$_->[8]" ) ){
            $duplicateFlag = 1;
        }
    }
    if( $duplicateflag == 0){
        $refToAdd = \@itemArray;
        push(@uniques, $refToAdd);
        $output .= "$itemArray[3]" . "\t$itemArray[8]" . "\t$itemArray[5]" . "\t$itemArray[7]\n";
    }
}
print $output

Ответы [ 4 ]

5 голосов
/ 10 мая 2011

Одна возможность: использовать хеши, чтобы определить, был ли элемент виден ранее. Немного упрощен из вашего кода:

my %dupHash;
while (my @itemArray = $sth->fetchrow_array() ) {
    my $uniqueItem = itemArray[4];
    if (not exists $dupHash{$uniqueItem}) {
        print "Item $uniqueItem\n";
        $dupHash{$uniqueItem} = \@itemArray;
    }
}

Хорошо, это очень упрощено, но вы поняли идею. Используя хэш со значениями, которые я хочу проверить, являются уникальными, я могу избежать двойной петли и эффективности алгоритма O 2 . (Черт! Все эти годы в колледже, наконец, окупились!).

Возможно, вы захотите использовать более сложный хеш-ключ, объединив все поля, в которых вы хотите искать дубликаты. Может быть, что-то вроде этого:

 # Probably could use join to make it more efficient...
 my $uniqueKay = "$item[3]:$item[4]:$item[5]:$item[6]:$item[7]:$item[8]";
 if (not exists $dupHash{$uniqueKey}) {

Главное избегать циклического повторения всех уникальных элементов снова и снова, если вы можете хранить их в хэше.

4 голосов
/ 10 мая 2011

Возможно:

$itemArray[8] == "$_->[8]"

должно быть:

$itemArray[8] eq "$_->[8]"

, чтобы соответствовать всем остальным.

Еще одна вещь, которая может решить вашу проблему, это удаление кавычеквокруг "$ _-> [8]".Зависит от ваших данных.

3 голосов
/ 10 мая 2011

Вы получаете все дубликаты, так как $ duplicateflag не определен в строке 13. Запуск синтаксического теста для вашего скрипта при включенном use strict; use warnings; выдает следующее предупреждение:

Global symbol "$duplicateflag" requires explicit package name at t10.pl line 18.

И если мы проанализируем ваше определение «этой» переменной, оно скажет:

my $duplicateFlag = 0;

То есть, у вас есть заглавная буква F, что означает, что $ duplicateflag - это не та же переменная, что и $ duplicateFlag. Проверка undef == 0 все еще выдает истинное значение и вызывает ложное срабатывание.

Чтобы избежать подобных проблем, всегда запускайте свои скрипты с

use strict;
use warnings;
1 голос
/ 10 мая 2011

SQL group by или select distinct - это способ сохранения уникальности строк в базе данных SQL.

Но если вы собираетесь делать это в Perl, я согласен, что хеш и ключи - это путь. Тем не менее, любой разделитель, который мы можем предложить, также может присутствовать в данных. Это дает вам возможность для неоднозначного матча. Один метод, основанный на хэше, является однозначным и использует естественные структуры Perl для разграничения ваших полей.

Вот почему я представляю следующее.

my %uniq;

while ( my @r = $sth->fetchrow_array()) {
    next unless $uniq{ $r[3] }{ $r[4] }{ $r[5] }{ $r[6] }{ $r[7] }{ $r[8] }++; 
    # unique code here
    #...
}

Это исключило бы временную переменную. И так исключен результат орфографических ошибок временной переменной. Однако USUW работает лучше для этих вещей: USUW = "use strict; use warnings;".

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...