Como obter itens exclusivos do Perl da lista

Tarefa. Em um programa na linguagem de programação Perl lista. Na lista há strings e números. Precisa de valores distintos a partir desta lista.

Solução usando a função uniq a partir de uma biblioteca List::Util

A forma mais simples e fácil para resolver este problema é usar o a função uniq a partir de uma biblioteca List::Util. Aqui está um exemplo de código:

▶ Run
#!/usr/bin/perl

use List::Util qw(uniq);
use Data::Dumper;

my @arr = uniq('one', 'one', 'b', 'one', 'b', 4);

print Dumper \@arr;

Se você salvar o texto em um arquivo script.ple então executar o console de perl script.pl, então aparecerá na tela:

$VAR1 = [
          'one',
          'b',
          4
        ];

A função uniq mantém a ordem dos elementos e ela funciona corretamente se a lista contiver uma undef.

Este código será executado a partir da versão Perl 5.26. Em versões anteriores do Perl contém a versão da biblioteca de List::Util que ainda não tenha a função de uniq. De modo que para usar esta solução terá que quer atualizar Perl, ou colocar a versão mais recente biblioteca List::Util.

A documentação oficial

Aqui está um trecho da saída do comando perldoc List::Util sobre a função uniq:

  uniq
        my @subset = uniq @values

    *Since version 1.45.*

    Filters a list of values to remove subsequent duplicates, as judged by a
    DWIM-ish string equality or "undef" test. Preserves the order of unique
    elements, and retains the first value of any duplicate set.

        my $count = uniq @values

    In scalar context, returns the number of elements that would have been
    returned as a list.

    The "undef" value is treated by this function as distinct from the empty
    string, and no warning will be produced. It is left as-is in the
    returned list. Subsequent "undef" values are still considered identical
    to the first, and will be removed.

Sua própria solução

Basta escrever sozinho uma versão simplificada da função uniq a partir de uma biblioteca List::Util:

▶ Run
#!/usr/bin/perl

use Data::Dumper;

sub uniq {
     my (@values) = @_;

     my %h = map {$_ => 1} @values;

     return keys %h;
}

my @arr = uniq('one', 'one', 'b', 'one', 'b', 4);

print Dumper \@arr;

Este código é imediatamente funciona em qualquer versão do Perl. Eis as três linhas de sava uniq:

  • my (@values) = @_; — colocou os argumentos, que são transmitidos em сабу na variável @values
  • my %h = map {$_ => 1} @values; — para cada item da @values criou uma lista de dois elementos — o elemento e a unidade, e os resultantes listas de se fundiram em uma única lista e atribuiu a esta lista хешу. O hash é desordenado conjunto de pares chave-valor. Uma chave pode ser apenas um valor. Graças a essa propriedade de hash são limpos todos os takes.
  • return keys %h; — de volta a lista consiste apenas de chaves de hash

Mas em comparação com a função de uniq a partir de uma biblioteca List::Util deste código, há desvantagens:

  • a nossa função uniq retorna os itens em ordem aleatória. Diferentes execuções de um mesmo código de levar a resultados diferentes (o valor que retorna a função de uniq serão os mesmos, mas eis a ordem em que eles estão localizados vai variar)
  • a nossa função não está a funcionar corretamente, se a lista tem undef. Nós usamos todos os valores da lista como chaves de hash. E undef não pode ser a chave хеше. Quando você tenta usar o undef como a chave será emitido um aviso e será usada uma seqüência de caracteres vazia em vez de undef.

Outros artigos