Collection d'objet

ViPHP
ViPHP | 928 Messages

13 juin 2007, 13:22

Dans ce cas tu peux créer un tableau avec des références sur tous tes objets qui sont encore vivants, et supprimés les entrées du tableau en cas de "mort". Ton array_rand() ne piochera ainsi que chez les vivants.

Eléphant du PHP | 113 Messages

15 juin 2007, 10:01

Oui c'est la solution que j'utilise actuellement.

Seulement le problème est que par exemple mon vaisseau peut avoir comme ordre de tirer uniquement sur les petits vaisseau ou inversement sur les gros.

Il me faut alors tirer une cible au hasard dans les vaisseaux vivants d'une certaine taille.

Puis après on peut demande qu'un vaisseau tire que sur un gros vaisseau qui a déja été endommager. ect......

dans ce cas la il faut passer par un filtrage non?

Administrateur PHPfrance
Administrateur PHPfrance | 3131 Messages

15 juin 2007, 14:04

Par curiosité (c'est à peine HS, disons un peu en retard ;)) j'ai testé les différentes manières de récupérer un éléments de tableau au hasard :
// Entrée : tableau "simple" (non associatif)
// Sortie : un élément au hasard
function my_array_rand_value($tableau) {
	return $tableau[mt_rand(1,count($tableau)-1)];
}

// Entrée : tableau quelconque
// Sortie : un élément au hasard
function my_array_rand_value_assoc($tableau) {
	$values = array_values($tableau);
	return $values[mt_rand(0,count($tableau)-1)];
}

// Entrée : tableau quelconque
// Sortie : un élément au hasard
function array_rand_value($tableau) {
	return $tableau[array_rand($tableau)];
}

// Construction d'un tableau
$tableau = array();
$tableau_assoc = array();
for ($i=0; $i<$nbElements; $i++) {
	$tableau[] = uniqid();
	$tableau_assoc[uniqid()] = uniqid();
}
$bench->setMarker('Construction des tableaux de '.$nbElements.' éléments');

// Tests des 4 possibilités
for ($i=0; $i<$nbIterations; ++$i) $res = my_array_rand_value($tableau);
$bench->setMarker($nbIterations.' appels à my_array_rand_value($tableau)');
for ($i=0; $i<$nbIterations; ++$i) $res = my_array_rand_value_assoc($tableau_assoc);
$bench->setMarker($nbIterations.' appels à my_array_rand_value_assoc($tableau_assoc)');
for ($i=0; $i<$nbIterations; ++$i) $res = array_rand_value($tableau);
$bench->setMarker($nbIterations.' appels à array_rand_value($tableau)');
for ($i=0; $i<$nbIterations; ++$i) $res = array_rand_value($tableau_assoc);
$bench->setMarker($nbIterations.' appels à array_rand_value($tableau_assoc)');
Voici les résultats pour un tout petit tableau (5 éléments, 100'000 itérations) :
Image

Pour un tableau moyen (500 éléments, 100'000 itérations) :
Image

Pour un grand tableau (50'000 éléments, 1'000 itérations) :
Image

Si on compare avec les valeurs par itération en fonction du nombre d'éléments, c'est édifiant :
Image
Bien sûr il faut lire ça en ayant en tête que A et C sont sur des tableaux "simple" alors que B et D sont sur des tableaux associatifs, donc il aurait fallu comparer A/C et B/D, mais les résultats auraient été très proches étant donné que C/D est toujours très proche de 1.
Mais ce qui apparaît le plus flagrant, et qui est la donnée vraiment intéressante c'est que $tableau[mt_rand(0,count($tableau)-1)] se calcule en un temps totalement indépendant du nombre d'éléments du tableau, et ça c'est très fort ;) J'ai fait le test avec un tableau de 6'900'000 éléments (je ne peux pas plus avec ma RAM) et ça donne le même temps de 2.9 us.

En conclusion :
- Sur un tableau associatif il vaut TOUJOURS mieux utiliser array_rand(), le rapport passe vite à du 1 pour 10.
- Sur un tableau "simple" l'utilisation de mt_rand()+count() devient plus rapide à partir de 15-20 éléments, et avant elle est vraiment très proche. Donc il vaut quasiment toujours utiliser mt_rand+count ;) le rapport passe vite à du 1 pour 5.
- Si on peut utiliser un tableau simple au lieu d'un associatif, il vaut mieux utiliser le simple.

Eléphant du PHP | 113 Messages

18 juin 2007, 09:40

Dans le cadre de ma question il aurait été intéressant de prolonger le test en m'étant en scène cette fois ci un tirage aléatoire dans une collection d'objets.

Administrateur PHPfrance
Administrateur PHPfrance | 3088 Messages

18 juin 2007, 10:28

Ben c'est une sélection aléatoire sur un tableau, et comme ta "collection d'objet" n'est qu'un wrapper autour d'un tableau le principe reste le même (voir la méthode que j'ai posté plus haut).