64 votes

Comment puis-je comparer deux séries de 1000 numéros l'une par rapport à l'autre ?

Je dois vérifier environ 1000 numéros par rapport à 1000 autres numéros.

J'ai chargé les deux et les ai comparés côté serveur :

foreach( $numbers1 as $n1 ) {
  foreach( $numbers2 as $n2 ) {
    if( $n1 == $n2 ) {
      doBla();
    }
  }
}

Cela a pris beaucoup de temps, alors j'ai essayé d'effectuer la même comparaison côté client en utilisant deux fichiers cachés. div éléments. Puis on les a comparés en utilisant JavaScript. Il faut toujours 45 secondes pour charger la page (en utilisant des éléments cachés). div éléments).

Je n'ai pas besoin de charger les chiffres qui ne sont pas les mêmes.

Existe-t-il un algorithme plus rapide ? Je pense les comparer dans la base de données et ne charger que les numéros d'erreur, puis faire un appel Ajax pour les autres numéros sans erreur. Mais une base de données MySQL est-elle assez rapide ?

0 votes

S'il vous plaît voir ma réponse Je doute que l'optimisation de l'algorithme de recherche soit la réponse correcte .

129voto

Pointy Points 172438

Trier d'abord les listes. Ensuite, vous pouvez parcourir les deux listes depuis le début, en comparant au fur et à mesure.

La boucle ressemblerait à quelque chose comme ceci :

var A = getFirstArray().sort(), B = getSecondArray().sort();

var i = 0, j = 0;
while (i < A.length && j < B.length) {
    if (A[i] === B[j]) {
        doBla(A[i]);
        i++; j++;
    }
    else if (A[i] < B[j]) {
        i++;
    }
    else
        j++;
}

(C'est du JavaScript ; vous pourriez aussi le faire côté serveur, mais je ne connais pas le PHP).

Modifier - Pour être juste envers tous les fans de hashtable (que je respecte bien sûr), il est assez facile de faire cela en JavaScript :

var map = {};
for (var i = 0; i < B.length; ++i) map[B[i]] = true; // Assume integers.
for (var i = 0; i < A.length; ++i) if (map[A[i]]) doBla(A[i]);

Ou si les chiffres sont ou pourraient être des flottants :

var map = {};
for (var i = 0; i < B.length; ++i) map['' + B[i]] = true; // Assume integers.
for (var i = 0; i < A.length; ++i) if (map['' + A[i]]) doBla(A[i]);

Étant donné que le hachage des nombres est assez bon marché (même en JavaScript, la conversion en chaîne de caractères avant le hachage est étonnamment bon marché), cette opération serait assez rapide.

1 votes

Le triage lui-même prendra du temps. D'après la question, il n'est PAS clair pour moi si cette activité est ponctuelle.

4 votes

Si ce n'est pas le cas, alors... Si A est de taille n et B de taille m, cela prendra nlg(n)+mlg(m)+min(m,n) de temps, alors que, l'approche de l'OP est juste m.n ...

66 votes

Si m y n sont toutes deux grandes - comme stipulé dans la question - alors les tris seront absolument, définitivement plus rapides. Faites le calcul ! Le tri d'un tableau de 1000 éléments représente environ 3000 opérations, soit 3000+3000+1000. Mais 1000 * 1000 est 100 fois plus de travail .

85voto

0 votes

Cependant, les deux seraient O(n.log n) au mieux.

3 votes

@dhruvbird a posé la question suivante : "Je dois vérifier environ 1000 nombres contre 1000 autres nombres". La fonction PHP ci-dessus fait ce qui est demandé. La sortie renvoyée doit être le résultat souhaité que l'utilisateur peut facilement manipuler pour tirer parti de son doBla().

1 votes

"Théoriquement vrai, mais appeler une consultation de table de hachage O(log n) ne lui rend pas vraiment justice. En pratique, il se comporte plus comme O(1)

27voto

Preet Sangha Points 39414

En termes de base de données, il s'agit d'une jointure de 1000 lignes à 1000 autres lignes. N'importe quel système de base de données moderne peut gérer cela.

select x from table1
inner join table2
on table1.x = table2.y

donde table1 y table2 sont les lignes concernées et pourraient être la même table.

15 votes

+1, comme le dit Preet, faites attention à ce que ce soit un Db moderne, disons... post 1974 :P

0 votes

J'adorerais savoir comment les dbs de Codasyl auraient géré ça.

0 votes

Codasyl et IMS auraient plus de mal à mâcher du SQL, en effet. 1974 était une référence à l'année de parution de la norme SQL.

26voto

markmnl Points 3622

Ce que vous avez ne devrait pas prendre autant de temps - que fait doBla() ? Je pense que c'est ce qui prend le temps ? Comparer deux ensembles de 1000000 nombres avec le même algorithme ne prend pas de temps du tout

C'est hilarant - le nombre de techniques d'optimisation comme réponses - le problème n'est pas votre algorithme - c'est ce que doBla() fait qui prend le temps par un facteur beaucoup plus grand que n'importe quelle optimisation vous aiderait :) en particulier étant donné que les ensembles ne font que 1000 et que vous devez les trier en premier

4 votes

Je me demande pourquoi tu as été descendu ? Vous avez raison, bien sûr - même la comparaison par force brute qu'il a devrait être raisonnablement rapide. Il doit appeler doBla un grand nombre de fois dans le cas typique, ou cela prend beaucoup de temps à exécuter à chaque fois...

23voto

sod Points 1394

Peut-être qu'il suffit de croiser les valeurs des tableaux pour trouver les nombres existant dans les deux tableaux ?

$result = array_intersect($numbers1, $numbers2);
foreach ($result as $val)
  doBla();

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X