web-dev-qa-db-fra.com

Liste des techniques de comparaison pour des performances plus rapides

J'ai besoin de croiser les noms de deux listes et de trouver toutes les occurrences d'un nom dans l'autre. Les listes sont trop grandes, l'une a 50k éléments et l'autre 400k.

Pour une petite liste, j'utiliserais deux cycles foreach ou Linq, mais je ne peux pas exécuter le programme pendant des jours.

Quel est votre conseil pour effectuer des comparaisons rapides?

EDIT: Dans certains cas, j'ai besoin de trouver plus que l'occurrence sur la deuxième liste, en d'autres termes, tous les noms sont répétés et ont des informations différentes associées. L'intention est alors de fusionner les informations des deux sources.

7
cap7

Ma suggestion serait de glisser la grande liste dans un ensemble de hachage, puis de l'utiliser pour faire correspondre les éléments de la petite liste.

Un ensemble de hachage est une structure qui stocke des éléments dans une structure de mémoire indexable, comme un tableau, où la position de l'élément est égale à une valeur de hachage calculée à l'aide de l'objet. Cela signifie que la recherche d'une valeur dans le hachage est une opération relativement rapide; calculer le hachage de l'objet que vous recherchez, aller à cet index et vérifier les objets réels qui y sont stockés, ce qui pour une bonne implémentation sera un très petit nombre (les implémentations de hachage doivent trouver un équilibre entre la taille du hachage et donc le nombre d'éléments de première dimension, et le nombre de collisions et donc le nombre moyen d'articles dans chaque élément).

Idéalement, les hachages approchent d'un temps de recherche constant (en particulier, c'est O (log2 ^ HN) où H est la taille en bits de la fonction de hachage, donc pour tout N <2 ^ H, il est effectivement constant), donc globalement, votre algorithme de correspondance approcherait la complexité linéaire. Deux inconvénients majeurs sont d'abord que, sauf si vous avez accès à une implémentation efficace intégrée (Java HashMap est construit sur cette structure, tout comme la classe Dictionary de .NET), vous devez rouler votre propre qui est un peu de code, et deuxièmement , les hashsets sont de vrais porcs de mémoire car il y a pratiquement garanti qu'il y aura beaucoup d'espaces vides dans le tableau à moins que votre implémentation ne modifie sa fonction de hachage en fonction de la capacité attendue ou réelle (ce qui pourrait, si cela était naïvement, impliquer de hacher chaque élément plusieurs fois comme la première dimension est étendue pour limiter la croissance dans la deuxième dimension).

6
KeithS

Triez les deux listes avec un algorithme de tri efficace (ou assurez-vous que les listes sont "pré-triées" par la personne/quoi que ce soit qui les a créées).

Ensuite, si le prénom dans les deux listes est le même que vous avez trouvé une correspondance, sinon jetez celui qui est "plus tôt"; et faites-le jusqu'à ce que l'une des listes soit vide.

Un pseudo-code brut:

    do {
        status = compare(shortList[i], longList[j]);
        if(status == EQUAL) {
            // Found match!
            i++;
            j++;
        } else if(status == EARLIER) {
            // No match, discard first entry in short list
            i++;
        } else {
            // No match, discard first entry in long list
            j++;
        }
    } while( (i < shortListEntries) && (j < longListEntries) );
6
Brendan

Triez la petite liste avec un algorithme de tri efficace, parcourez la grande liste et pour chaque élément de la grande liste, utilisez une recherche binaire pour trouver s'il y a un élément correspondant dans la petite liste.

2
Pieter B

Trouver des choses dans un ensemble qui correspondent à celles d'un autre ensemble et fusionner des données est quelque chose que les bases de données relationnelles Excel. Si c'est quelque chose que vous devez faire beaucoup, le chargement de vos listes dans des tables dans votre choix de base de données SQL est probablement votre meilleure option.

0
Ryathal