Eu estou tentando descobrir uma maneira de verificar a existência de um valor em uma matriz sem percorrer a matriz.
Estou lendo um arquivo para um parâmetro. Eu tenho uma longa lista de parâmetros com os quais não quero lidar. Eu coloquei esses parâmetros indesejados em uma matriz @badparams
.
Quero ler um novo parâmetro e, se ele não existir @badparams
, processá-lo. Se existir @badparams
, vá para a próxima leitura.
perl
arrays
comparison
Mel
fonte
fonte
Respostas:
Simplesmente transforme a matriz em um hash:
Você também pode adicionar mais parâmetros (exclusivos) à lista:
E depois obtenha uma lista de parâmetros (únicos) de volta:
fonte
1
novamente.Melhor finalidade geral - matrizes especialmente curtas (1000 itens ou menos) e codificadores que não têm certeza de quais otimizações melhor atendem às suas necessidades.
Foi mencionado que o grep passa por todos os valores, mesmo que o primeiro valor na matriz corresponda. Isso é verdade, porém o grep ainda é extremamente rápido na maioria dos casos . Se você estiver falando de matrizes curtas (menos de 1.000 itens), a maioria dos algoritmos será bastante rápida. Se você está falando de matrizes muito longas (1.000.000 de itens), o grep é aceitavelmente rápido, independentemente de o item ser o primeiro, o meio ou o último da matriz.
Casos de otimização para matrizes mais longas:
Se sua matriz estiver classificada , use uma "pesquisa binária".
Se a mesma matriz for repetidamente pesquisada várias vezes, copie-a primeiro para um hash e depois verifique o hash. Se a memória for uma preocupação, mova cada item da matriz para o hash. Mais memória eficiente, mas destrói a matriz original.
Se os mesmos valores forem pesquisados repetidamente na matriz, crie um cache preguiçosamente. (à medida que cada item é pesquisado, verifique primeiro se o resultado da pesquisa foi armazenado em um hash persistente. se o resultado da pesquisa não for encontrado no hash, pesquise na matriz e coloque o resultado no hash persistente para que da próxima vez encontre-o no hash e pule a pesquisa).
Nota: essas otimizações só serão mais rápidas ao lidar com matrizes longas. Não otimize demais.
fonte
Você pode usar o recurso smartmatch no Perl 5.10 da seguinte maneira:
Para a pesquisa literal de valor, fazer o procedimento abaixo.
Para pesquisa escalar, o procedimento abaixo funcionará como acima.
Para a matriz embutida que estiver fazendo abaixo, funcionará como acima.
No Perl 5.18, o smartmatch é marcado como experimental, portanto, você precisa desativar os avisos ativando o pragma experimental , adicionando abaixo ao seu script / módulo:
Como alternativa, se você deseja evitar o uso de smartmatch - então, como Aaron disse, use:
fonte
use experimental 'smartmatch'
é recomendada. Como tenho controle da minha versão perl (sistema interno), uso ano warnings 'experimental::smartmatch';
instruçãoEsta postagem do blog discute as melhores respostas para esta pergunta.
Como um breve resumo, se você pode instalar os módulos CPAN, as soluções mais legíveis são:
ou
No entanto, um idioma mais comum é:
Mas por favor, não use a
first()
função! Ele não expressa a intenção do seu código. Não use o~~
operador "Correspondência inteligente": está quebrado. E não usegrep()
nem a solução com um hash: eles repetem a lista inteira.any()
irá parar assim que encontrar seu valor.Confira a postagem do blog para mais detalhes.
fonte
use List::Util qw(any);
.List::Util
está nos módulos principais .Método 1: grep (pode ser cuidadoso enquanto se espera que o valor seja um regex).
Tente evitar o uso
grep
, se estiver procurando recursos.Método 2: pesquisa linear
Método 3: usar um hash
Método 4: smartmatch
(adicionado no Perl 5.10, marcado é experimental no Perl 5.18).
Método 5: usar o módulo
List::MoreUtils
fonte
O benchmark do @ eakssjo está quebrado - mede a criação de hashes em loop versus a criação de regexes em loop. Versão fixa (mais eu adicionei
List::Util::first
eList::MoreUtils::any
):E resultado (é para iterações 100_000, dez vezes mais do que na resposta do @ eakssjo):
fonte
Embora seja fácil de usar, parece que a solução converter em hash custa bastante desempenho, o que foi um problema para mim.
Resultado do teste de benchmark:
fonte
List::Util::first
é mais rápido, pois para de iterar quando encontra uma correspondência.grep
é significativamente mais lenta que a criação de hash e a pesquisa, uma vez que o primeiro é O (n) e o último O (1). Apenas faça a criação de hash apenas uma vez (fora do loop) e pré-calcule o regex para medir apenas os métodos ( veja minha resposta ).@files é uma matriz existente
/^2interest\dd.[\dd[A-za-zunette?/ = valores começando em 2 aqui você pode colocar qualquer expressão regular
fonte
Você certamente quer um hash aqui. Coloque os parâmetros incorretos como chaves no hash e decida se existe um parâmetro específico no hash.
Se você estiver realmente interessado em fazê-lo com uma matriz, veja
List::Util
ouList::MoreUtils
fonte
Há duas maneiras de você fazer isto. Você pode usar os valores lançados em um hash para uma tabela de pesquisa, conforme sugerido pelas outras postagens. (Vou adicionar apenas outro idioma.)
Mas se são dados principalmente de caracteres de palavras e não muitos meta, você pode despejá-los em uma alternância de regex:
Essa solução teria que ser ajustada para os tipos de "valores ruins" que você está procurando. E, novamente, pode ser totalmente inapropriado para certos tipos de strings, portanto, ressalte o emptor .
fonte
@bad_param_lookup{@bad_params} = ()
, mas precisaria usarexists
para testar a associação.Convém verificar a consistência numérica dos espaços à esquerda
fonte