Valeurs correspondantes dans le tableau de chaînes
Problème: à la Recherche d'un moyen plus efficace de trouver s'il existe une correspondance exacte de la valeur dans un tableau 1d-essentiellement de l'un booléen true/false
.
Suis-je surplombant quelque chose d'évident? Ou suis-je simplement à l'aide de la mauvaise structure de données, en utilisant un tableau quand je devrais probablement être l'aide d'un objet de collection ou d'un dictionnaire? Dans ce dernier j'ai pu vérifier la .Contains
ou .Exists
méthode, respectivement
Dans Excel que je puisse vérifier une valeur dans un tableau de vecteurs comme:
If Not IsError(Application.Match(strSearch, varToSearch, False)) Then
' Do stuff
End If
Cela renvoie une correspondance exacte de l'indice, évidemment soumis à des limitations d' Match
fonction qui ne trouve que le première valeur correspondante dans ce contexte. C'est une méthode couramment utilisée, et celui que j'ai utilisé pendant un long moment, trop.
C'est assez satisfaisante pour Excel-mais quelles autres applications?
Dans d'autres applications, je peux faire quasiment la même chose, mais nécessite l'activation de référence à la bibliothèque d'objet Excel, et ensuite:
If Not IsError(Excel.Application.match(...))
Qui semble idiote, bien, et est très difficile à gérer sur les fichiers distribués à cause des autorisations/trust center/etc.
J'ai essayé d'utiliser le Filtre() fonction:
If Not Ubound(Filter(varToSearch, strSearch)) = -1 Then
'do stuff
End If
Mais le problème avec cette approche est que Filter
retourne un tableau de correspondances partielles, plutôt qu'un tableau de correspondances exactes. (Je n'ai aucune idée de pourquoi il serait utile de revenir sous-chaîne/les correspondances partielles.)
L'autre alternative est littéralement itérer sur chaque valeur dans le tableau (ce qui est aussi très couramment utilisé, je pense) -- ce qui semble encore plus inutilement lourd que d'appeler sur Excel Match
fonction.
For each v in vArray
If v = strSearch Then
' do stuff
End If
Next
source d'informationauteur David Zemens
Vous devez vous connecter pour publier un commentaire.
Si nous allons parler de performances, alors il n'y a pas substutute pour l'exécution de certains tests. Dans mon expérience de l'Application.Match() est jusqu'à dix fois plus lent que l'appel d'une fonction qui utilise une boucle.
De sortie:
J'ai utilisé de regarder pour une meilleure remplacer la solution. Il doit travailler pour simple de trouver ainsi.
Pour trouver la première occurrence d'une chaîne de caractères, vous pouvez essayer d'utiliser ce code:
Si vous voulez trouver toutes les instances essayer de le ci-dessous.
Gardez à l'esprit que si il y a plusieurs instances de la chaîne recherchée dans une cellule, il va retourner qu'un seul résultat dû à la spécificité de FindNext.
Encore, si vous avez besoin d'un code pour remplacer les valeurs avec un autre, j'aimerais utiliser la première solution, mais vous auriez à changer un peu.
"Une manière plus efficace (par rapport à
Application.Match
)de déterminer si une chaîne de valeur existe dans un tableau":Je crois qu'il n'est pas de moyen plus efficace que celui que vous utilisez, c'est à dire,
Application.Match
.Tableaux permettent un accès efficace dans n'importe quel élément, si nous savons l'indice de cet élément. Si nous voulons faire quelque chose par la valeur de l'élément (même vérifier si un élément existe), nous avons à analyser tous les éléments du tableau dans le pire des cas. Par conséquent, le pire des cas, les besoins
n
élément comparaisons, oùn
est la taille du tableau. De sorte que le maximum de temps, nous avons besoin de trouver si un élément existe est linéaire en la taille de l'entrée, c'est à dire,O(n)
. Cela s'applique à tout langage qui utilise des réseaux classiques.Le seul cas où nous pouvons être plus efficaces, c'est quand le tableau a la structure spéciale. Pour votre exemple, si les éléments du tableau sont triées (par exemple par ordre alphabétique), alors nous n'avons pas besoin de scanner toute la table: on compare avec le milieu de l'élément, puis de les comparer avec la gauche ou la partie droite du tableau (binaire de recherche). Mais sans assumer aucune structure particulière, il n'y a pas d'espoir..
La
Dictionary/Collection
comme vous le point, vous propose constante de la clé d'accès à leurs éléments (O(1)
). Ce qui est peut-être pas très bien documenté, c'est que l'on peut aussi avoir d'accès index pour le dictionnaire des éléments (les Clés et les Éléments): l'ordre dans lequel les éléments sont entrés dans leDictionary
est préservée. Leur principal inconvénient est qu'ils utilisent plus de mémoire que les deux objets sont stockés pour chaque élément.Pour conclure, bien que
If Not IsError(Excel.Application.match(...))
semble idiot, c'est encore la façon la plus efficace (au moins en théorie). Sur les problèmes d'autorisation de ma connaissance est très limitée. En fonction de l'application hôte, il y a toujours quelquesFind
-type de fonctions (C++
afind
etfind_if
par exemple).J'espère que ça aide!
Modifier
Je voudrais ajouter un couple de pensées, d'après la lecture de la version modifiée de la poste et de Tim réponse. Le texte ci-dessus est en se concentrant sur la durée théorique de la complexité des différentes structures de données et ignore les questions de mise en œuvre. Je pense que l'esprit de la question était plutôt, "une certaine structure de données (array)", ce qui est la façon la plus efficace dans la pratique de la vérification de l'existence.
À cette fin, Tim réponse est un eye-opener.
Les classiques de la règle "si
VBA
peut le faire pour vous, alors ne pas écrire de nouveau toi-même" n'est pas toujours vrai. Des opérations simples comme les boucles et les comparaisons peuvent être plus rapides que "agreegate"VBA
fonctions. Deux liens intéressants sont ici et ici.