Pour le bloc de code suivant:
For I = 0 To listOfStrings.Count - 1
If myString.Contains(lstOfStrings.Item(I)) Then
Return True
End If
Next
Return False
La sortie est:
Cas 1:
myString: C:\Files\myfile.doc
listOfString: C:\Files\, C:\Files2\
Result: True
Cas 2:
myString: C:\Files3\myfile.doc
listOfString: C:\Files\, C:\Files2\
Result: False
La liste (listOfStrings) peut contenir plusieurs éléments (minimum 20) et elle doit être comparée à des milliers de chaînes (comme myString).
Existe-t-il une meilleure façon (plus efficace) d'écrire ce code?
la source
quand vous construisez vos chaînes, cela devrait être comme ça
la source
Il y avait un certain nombre de suggestions à partir d'une question similaire précédente " Meilleur moyen de tester la chaîne existante par rapport à une grande liste de comparables ".
Regex pourrait être suffisant pour vos besoins. L'expression serait une concaténation de toutes les sous-chaînes candidates, avec un
|
opérateur OR " " entre elles. Bien sûr, vous devrez faire attention aux caractères non échappés lors de la construction de l'expression, ou à un échec de la compilation en raison de la complexité ou des limitations de taille.Une autre façon de faire cela serait de construire une structure de données trie pour représenter toutes les sous-chaînes candidates (cela peut en quelque sorte dupliquer ce que fait le matcher regex). Au fur et à mesure que vous parcourez chaque caractère de la chaîne de test, vous créez un nouveau pointeur vers la racine du trie et avancez les pointeurs existants vers l'enfant approprié (le cas échéant). Vous obtenez une correspondance lorsqu'un pointeur atteint une feuille.
la source
J'ai aimé la réponse de Marc, mais j'avais besoin de la correspondance Contains pour être CaSe InSenSiTiVe.
C'était la solution:
la source
En fonction de vos modèles, une amélioration serait de passer à l'utilisation de StartsWith au lieu de Contains. StartsWith n'a qu'à parcourir chaque chaîne jusqu'à ce qu'il trouve la première discordance au lieu d'avoir à redémarrer la recherche à chaque position de caractère lorsqu'il en trouve une.
En outre, en fonction de vos modèles, il semble que vous puissiez extraire la première partie du chemin de myString, puis inverser la comparaison - en recherchant le chemin de départ de myString dans la liste des chaînes plutôt que l'inverse.
EDIT : Ce serait encore plus rapide en utilisant l'idée de HashSet @Marc Gravell mentionne puisque vous pouvez changer
Contains
àContainsKey
et la recherche serait O (1) au lieu de O (N). Vous devrez vous assurer que les chemins correspondent exactement. Notez que ce n'est pas une solution générale comme celle de @Marc Gravell mais qu'elle est adaptée à vos exemples.Désolé pour l'exemple C #. Je n'ai pas eu assez de café pour traduire en VB.
la source
Ancienne question. Mais depuis
VB.NET
était l'exigence initiale. En utilisant les mêmes valeurs de la réponse acceptée:la source
Avez-vous testé la vitesse?
c.-à-d. Avez-vous créé un échantillon de données et l'avez-vous profilé? Ce n'est peut-être pas aussi grave que vous le pensez.
Cela pourrait aussi être quelque chose que vous pourriez créer dans un fil séparé et donner l'illusion de la vitesse!
la source
Si la vitesse est critique, vous voudrez peut-être rechercher l' algorithme Aho-Corasick pour les ensembles de modèles.
C'est un essai avec des liens d'échec, c'est-à-dire que la complexité est O (n + m + k), où n est la longueur du texte d'entrée, m la longueur cumulée des motifs et k le nombre de correspondances. Il vous suffit de modifier l'algorithme pour qu'il s'arrête une fois la première correspondance trouvée.
la source
la source
L'inconvénient de la
Contains
méthode est qu'elle ne permet pas de spécifier le type de comparaison qui est souvent important lors de la comparaison de chaînes. Il est toujours sensible à la culture et à la casse. Je pense donc que la réponse de WhoIsRich est précieuse, je veux juste montrer une alternative plus simple:la source