Para o seguinte bloco de código:
For I = 0 To listOfStrings.Count - 1
If myString.Contains(lstOfStrings.Item(I)) Then
Return True
End If
Next
Return False
A saída é:
Caso 1:
myString: C:\Files\myfile.doc
listOfString: C:\Files\, C:\Files2\
Result: True
Caso 2:
myString: C:\Files3\myfile.doc
listOfString: C:\Files\, C:\Files2\
Result: False
A lista (listOfStrings) pode conter vários itens (no mínimo 20) e deve ser verificada em milhares de strings (como myString).
Existe uma maneira melhor (mais eficiente) de escrever esse código?
fonte
quando você constrói suas cordas, deve ser assim
fonte
Houve várias sugestões de uma pergunta semelhante anterior " Melhor maneira de testar a cadeia existente em uma grande lista de comparáveis ".
Regex pode ser suficiente para sua exigência. A expressão seria uma concatenação de todas as substrings candidatas, com um
|
operador OR " " entre elas. Obviamente, você deve ter cuidado com caracteres não escapados ao criar a expressão ou com uma falha na compilação devido a limitações de complexidade ou tamanho.Outra maneira de fazer isso seria construir uma estrutura de dados trie para representar todas as substrings candidatas (isso pode duplicar o que o correspondente do regex está fazendo). À medida que você percorre cada caractere na sequência de teste, você cria um novo ponteiro para a raiz da árvore e avança os ponteiros existentes para o filho apropriado (se houver). Você obtém uma correspondência quando qualquer ponteiro atinge uma folha.
fonte
Gostei da resposta de Marc, mas precisava da correspondência Contains para ser CaSe InSenSiTiVe.
Esta foi a solução:
fonte
Com base em seus padrões, uma melhoria seria mudar para o uso de StartsWith em vez de Contains. StartsWith precisa apenas percorrer cada sequência até encontrar a primeira incompatibilidade, em vez de ter que reiniciar a pesquisa em todas as posições de caracteres quando encontrar uma.
Além disso, com base em seus padrões, parece que você pode extrair a primeira parte do caminho para myString e reverter a comparação - procurando o caminho inicial de myString na lista de strings e não o contrário.
EDIT : Isso seria ainda mais rápido usando a idéia do HashSet que @Marc Gravell menciona, já que você pode mudar
Contains
paraContainsKey
e a pesquisa seria O (1) em vez de O (N). Você precisaria garantir que os caminhos correspondam exatamente. Observe que essa não é uma solução geral, como é a de @Marc Gravell, mas é adaptada aos seus exemplos.Desculpe pelo exemplo de C #. Não tomei café suficiente para traduzir para o VB.
fonte
Pergunta antiga. Mas desde que
VB.NET
era o requisito original. Usando os mesmos valores da resposta aceita:fonte
Você já testou a velocidade?
Você criou um conjunto de dados de amostra e criou um perfil? Pode não ser tão ruim quanto você pensa.
Isso também pode ser algo que você pode gerar em um segmento separado e dar a ilusão de velocidade!
fonte
Se a velocidade for crítica, convém procurar o algoritmo Aho-Corasick para obter conjuntos de padrões.
É um experimento com links de falha, ou seja, a complexidade é O (n + m + k), onde n é o comprimento do texto de entrada, m o comprimento acumulado dos padrões e k o número de correspondências. Você apenas precisa modificar o algoritmo para finalizar após a primeira correspondência ser encontrada.
fonte
fonte
A desvantagem do
Contains
método é que ele não permite especificar o tipo de comparação que geralmente é importante na comparação de strings. É sempre sensível à cultura e ao caso. Então, acho que a resposta do WhoIsRich é valiosa, só quero mostrar uma alternativa mais simples:fonte