Удалить дубликаты из 2D-массива в Perl - PullRequest
0 голосов
/ 18 января 2019

У меня есть двумерный массив в Perl, данные которого поступают в виде строк в формате html из БД, как показано ниже:

<tr><td>Rafa</td><td>Nadal</td><td>Data1</td></tr>,
<tr><td>Goran</td><td>Ivan</td><td>Data2</td></tr>,
<tr><td>Leander</td><td>Paes</td><td>Data2</td></tr>,
<tr><td>Leander</td><td>Paes</td><td>Data2</td></tr>

Я хочу удалить дублирующиеся строки из массива. "<tr><td>Leander</td><td>Paes</td><td>Data2</td></tr>" следует удалить в вышеуказанном случае. Я попробовал приведенный ниже фрагмент кода, но он не работает.

sub unique {
     my %seen;
     grep ! $seen{ join $;, @$_ }++, @_
}

Ответы [ 2 ]

0 голосов
/ 18 января 2019

Показанный саб подходит для работы с массивом, который для элементов имеет ссылки на массив.Это действительно основной способ организации 2D-данных, где ваши строки представляют собой arrayrefs.

Существуют модули, которые могут быть использованы для этого, но этот старый добрый метод также отлично работает

use warnings;
use strict;    
use Data::Dump qw(dd);

sub uniq_arys {
    my %seen; 
    grep { not $seen{join $;, @$_}++ } @_; 
} 

my @data = ( 
    [ qw(one two three) ],  
    [ qw(ten eleven twelve) ],  
    [ qw(10 11 12) ],  
    [ qw(ten eleven twelve) ],  
); 

my @data_uniq = uniq_arys(@data); 

dd \@data_uniq;

Печатается, как и ожидалось (последняя строка пропала), используя Data :: Dump для отображения данных.

Подпрограмма работает путем объединения каждого массива в строку, после чего они проверяются на наличие дубликатов.используя хеш. $; - это индекс-разделитель , и вместо него пустая строка ''.

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


Пример модуля: используйте uniq_by из List :: UtilsBy

use List::UtilsBy qw(uniq_by);

my @no_dupes = uniq_by { join '', @$_ } @data;

Thisболее или менее совпадает с приведенным выше.

0 голосов
/ 18 января 2019

Первое: вам действительно следует стараться не использовать устаревший синтаксис Perl и побочные эффекты.

Второе: ответ зависит от структуры данных, которую вы генерируете из входных данных. Вот два примера реализации:

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

# 2D Array: list of array references
my @data = (
    ['Rafa', 'Nadal', 'Data1'],
    ['Goran', 'Ivan', 'Data2'],
    ['Leander', 'Paes', 'Data2'],
    ['Leander', 'Paes', 'Data2'],
);
my %seen;

foreach my $unique (
    grep {
        not $seen{
            join('', @{ $_ })
        }++
    } @data
) {
    print join(',', @{ $unique }), "\n";
}
print "\n";

# List of "objects", keys are table column names
@data = (
    { first => 'Rafa',    last => 'Nadal', data => 'Data1' },
    { first => 'Goran',   last => 'Ivan',  data => 'Data2' },
    { first => 'Leander', last => 'Paes',  data => 'Data2' },
    { first => 'Leander', last => 'Paes',  data => 'Data2' },
);
%seen = ();

my @key_order = qw(first last data);

foreach my $unique (
    grep {
        not $seen{ 
            join('', @{ $_ }{ @key_order } )
        }++
    } @data
) {
    print join(',', @{ $unique }{ @key_order }), "\n";
}

Выход:

$ perl dummy.pl
Rafa,Nadal,Data1
Goran,Ivan,Data2
Leander,Paes,Data2

Rafa,Nadal,Data1
Goran,Ivan,Data2
Leander,Paes,Data2
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...