8791 sujets

Développement web côté serveur, CMS

Pages :
Bonjour,


J'ai un code qui se répète et je voudrais en faire une boucle ou une fonction récursive.

J'ai une fonction qui contient un foreach et qui exécute un code, ce foreach contient un autre foreach qui exécute le code, qui contient un foreach etc... Le problème c'est que ça fait beaucoup de foreach dans d'autres foreach, surtout que je voudrais que ça se répète beaucoup beaucoup de fois !

J'ai un code qui ressemble à ça :


<?php

case_petit_nbr_candidats();

$sauvegarde_grille = $grille;
if (is_array($liste_candidats[$ligne_min][$col_min]))
{
	foreach ($liste_candidats[$ligne_min][$col_min] as $cle => $value)
	{
		$grille = $sauvegarde_grille;
		$grille[$ligne_min][$col_min] = $value;

		// code...
		
		verif_grille_pleine();
	
		if ($erreur_grille_pleine == 0)
		{
			echo "grille pleine";
		}
		else
		{
			case_petit_nbr_candidats2();

			$sauvegarde_grille2 = $grille;
			if (is_array($liste_candidats[$ligne_min2][$col_min2]))
			{
				foreach ($liste_candidats[$ligne_min2][$col_min2] as $cle => $value)
				{
					$grille = $sauvegarde_grille2;
					$grille[$ligne_min2][$col_min2] = $value;

					// code...
					
					verif_grille_pleine();
				
					if ($erreur_grille_pleine == 0)
					{
						echo "grille pleine";
					}
					else
					{
						case_petit_nbr_candidats3();

						$sauvegarde_grille3 = $grille;
						if (is_array($liste_candidats[$ligne_min3][$col_min3]))
						{
							foreach ($liste_candidats[$ligne_min3][$col_min3] as $cle => $value)
							{
								$grille = $sauvegarde_grille3;
								$grille[$ligne_min3][$col_min3] = $value;

								// code...
								
								verif_grille_pleine();
							
								if ($erreur_grille_pleine == 0)
								{
									echo "grille pleine";
								}
								else
								{
									case_petit_nbr_candidats4();
									// ....
									// ....
								}
								
								
								
							}
							
						
						}
					}
					
					
				
				}
				
			
			}
		}
		
		
		
	}
	

}

?>



Donc le code se répète à chaque entrée dans un autre foreach, le problème est que je dois à chaque fois faire une fonction différente case_petit_nbr_candidats(), case_petit_nbr_candidats2(), case_petit_nbr_candidats3(), parce que sinon d'un foreach imbriqué à l'autre, les valeurs se mélangent, puis pareil pour les vairables $ligne et $col, où je suis obligé de les différencier, sinon les valeurs se mélangent...

Donc je voudrais faire une boucle ou fonction qui permet de répéter ce code à chaque fois dans un autre foreach mais le problème c'est que les variables ont le même nom Smiley ohwell


Merci à vous !
Modifié par Crousti2 (03 Aug 2012 - 15:30)
Le principe de récursivité est simple, tu rappel la fonction dans sa procédure interne, il faut surtout garder a l'esprit qu'il doit y avoir un arrêt a un moment ou a un autre:



fonction recursive($nbRecurs)
{
  echo $nbRecurs;

  $nbRecurs--;

  if($nbRecurs)
  {
    recursive($nbRecurs);
    return;
  }

  echo $nbRecurs;
}

recursive(10);


Ici typiquement, on décrémente un nombre jusqu'à ce que celui ci arrive a 0, aprés on s'arrête.

Dans ton cas, j'ai du mal a comprendre ce que doit faire ton script mais je pense que ton tableau n'est pas formaté de manière optimale pour faire ce que tu souhaite.

Edit: Garde aussi a l'esprit que plus tes fonctions sont génériques et paramétrables, moins tu en aura à faire.
La meilleur pratique étant de procéder par niveau (fonctions bas niveau complexes, uniquement appelé dans des fonctions de plsu haut niveau et quasi jamais par le développeur lui même et fonctions de haut niveau simples a comprendre et a paramétrer par le développeur)
Modifié par JJK801 (03 Aug 2012 - 16:18)
Merci d'avoir répondu !


Oui je comprends très bien le principe de la récursivité, le problème est que mes variables portent alors le même nom mais ne doivent pas contenir la même chose Smiley biggol !

Ce script sert à la résolution d'un sudoku par force brute, il fonctionne mais il doit être répété plusieurs fois pour être plus efficace, pour l'instant je l'ai répété manuellement 9 fois, c'est long donc je voudrais le condenser, afin qu'il soit répété automatiquement.
Modifié par Crousti2 (03 Aug 2012 - 16:15)
Je comprends pas ce que tu veux dire par "le problème est que mes variables portent alors le même nom mais ne doivent pas contenir la même chose"... Cette phrase me fait un peu faire la même tête que ton avatar. En quoi est-ce un problème si leur portée n'est que celle de la fonction ?
Modifié par Gothor (03 Aug 2012 - 16:21)
Smiley rolleyes

Si j'enlève les numéros au niveau des variables $ligne et $col... et aussi aux fonctions case_petit_nbr_candidats() les valeurs se "mélangent"...

Dans le premier foreach par exemple $ligne = 1, dans le foreach imbriqué cette valeur passera à 2, donc elle va aussi être modifié dans le 1er foreach, alors que ce n'est pas ce qu'on veut...

Donc il faut différencier toutes ces variables et fonctions... et c'est bien à cause de ça que j'arrive pas à tout regrouper pour en faire une fonction récursive, ou une boucle....

La fonction case_petit_nbr_candidats() permet d'avoir les variables $ligne, $col, $ligne2, $col2....




Exemple pour bien comprendre:


foreach // ce foreach parcours un array, et donne successivement les valeurs 3 puis 5 (par exemple)
{
foreach // ce foreach parcours un array et donne successivement les valeurs 8 et 6
{
// on veut alors qu'il y ait d'abord les combinaisons 3-8, puis 3-6, puis 5-8 puis 5-6

// le problème si les variables portent le même nom lorsque ce foreach va donner la valeur 8
// elle va aussi être modifié dans le premier foreach, donc tout sera faussé !
}
}
Modifié par Crousti2 (03 Aug 2012 - 16:33)
Bonjour,

si tu utilises une fonction récursive avec en argument $liste_candidats, tu ne risqueras plus que tes valeurs se "mélangent" puisque en php tous les arguments des fonctions sont passés par valeur (par défaut).

Tu ne donnes qu’une partie de ton code, c’est donc difficile de t’aider mais je verrais bien une fonction ayant cette tête :

function resolutionRecursive($liste_candidats, $intNiveauRecursivite) {
	if ($intNiveauRecursivite <= 0) {
		// Cas trivial
	} else {
		if (is_array($liste_candidats[$ligne_min ][$col_min ])){foreach ($liste_candidats[$ligne_min ][$col_min ] as $cle => $value){$grille = $sauvegarde_grille ;$grille[$ligne_min ][$col_min ] = $value;/* code...*/verif_grille_pleine();if ($erreur_grille_pleine == 0){echo "grille pleine";}else{case_petit_nbr_candidats2();$sauvegarde_grille2 = $grille;}}
			resolutionRecursive($liste_candidats, $intNiveauRecursivite - 1);
		}
	}
}
Bonjour,


Merci pour ta réponse, mais ça ne marche pas, vu qu'il faut que les foreach soient imbriqués...

De plus les variables $ligne $col et $liste_candidats sont passées en global dans la fonction, afin de les utiliser dans toutes les fonctions du système de résolution.


Puis même si je fais quelque chose du genre :

<?php
function recursive()
{
  foreach ...
  {
     ...
     recursive();
  }
}
?>


Ca ne peut pas marcher, les variables portant le même nom, vont se mélanger vu qu'il y a des foreach imbriqués.
Modifié par Crousti2 (03 Aug 2012 - 17:56)
Et comme ça :

$nombreDeForeachImbriques = 4;

/* Premier appel de la fonction $intNiveauRecursivite = 0 */
function resolutionRecursive($intNiveauRecursivite) {
	if ($intNiveauRecursivite >= $nombreDeForeachImbriques) {
		// Cas trivial
	} else {
		// $i est un suffixe que l’on va rajouter à ligne_min et col_min
		$i = ($intNiveauRecursivite === 0 ? '' : $intNiveauRecursivite + 1);
		if (is_array($liste_candidats[${'ligne_min' . $i}][${'col_min' . $i}])){foreach ($liste_candidats[${'ligne_min' . $i}][${'col_min' . $i}] as $cle => $value){$grille = $sauvegarde_grille ;$grille[${'ligne_min' . $i}][${'col_min' . $i}] = $value;/* code...*/verif_grille_pleine();if ($erreur_grille_pleine == 0){echo "grille pleine";}else{case_petit_nbr_candidats($intNiveauRecursivite);${'sauvegarde_grille' . $i} = $grille;}}
			resolutionRecursive($liste_candidats, $intNiveauRecursivite + 1);
		}
	}
}

resolutionRecursive(0);

P.S. La nouvelle fonction case_petit_nbr_candidats() prendra comme argument le niveau de récursivité et il serait plus propre d’utiliser des tableaux plutôt que ces variables dynamiques, mais on est en dev.
Je vais essayer, par contre le problème c'est la communication des variables $ligne_min et $col_min entre la fonction case_petit_nbr_candidats() et resolutionRecursive() du coups...

Et comment ça il faudrait plus utiliser des tableaux, à quel niveau ?

Et enfin je ne comprends pas du tout cette ligne :

$i = ($intNiveauRecursivite === 0 ? '' : $intNiveauRecursivite + 1);

Smiley rolleyes
Modifié par Crousti2 (03 Aug 2012 - 20:04)
$i = ($intNiveauRecursivite === 0 ? '' : $intNiveauRecursivite + 1);
c’est la même chose que
if ($intNiveauRecursivite === 0) {
   $i = '';
} else {
   $i = $intNiveauRecursivite + 1;
}


Après la remarque pour les tableaux il vaudrait mieux utiliser des $ligne_min[$i] et $col_min[$i] plutôt que les variables dynamiques ${'ligne_min' . $i} qui sont plus tordues (il faut aller au plus simple notamment si tu reprends ton code plusieurs mois après). Je crois en plus que les variables dynamiques sont un peu plus lentes à l’exécution.
D'accord, merci, j'ai appris quelque chose avec le $i = ($intNiveauRecursivite === 0 ? '' : $intNiveauRecursivite + 1); que j'avoue est très bizarre Smiley lol Ca a un nom ce genre d'écriture ?
J'ai jamais vu ...

J'ai aussi appris a modifier le nom d'une variable avec une autre avec ${'ligne_min' . $i}, c'est cool merci !

Maintenant je vais tester le code et je te dis si ça tient la route !
Modifié par Crousti2 (03 Aug 2012 - 21:45)
Bonjour,


Bon finalement le code ne marchait pas, mais j'ai repris mon code à moi et je l'ai fais dans le même genre et là ça marche !! Je ne pensais pas que ça allait marcher Smiley lol

Mon résolveur de sudoku est maintenant terminé et opérationnel Smiley lol

Merci beaucoup à vous ! Smiley cligne
Modifié par Crousti2 (05 Aug 2012 - 09:15)
Hello,

La ligne de code que tu ne connaissais pas, c'est une opération ternaire.

D'ailleurs si le code ne marchais pas, c'est parce qu'il y avait une petite erreur à ce niveau :

$i = ($intNiveauRecursivite === 0 ? '' : $intNiveauRecursivite + 1);


A remplacer par :

$i = ($intNiveauRecursivite === 0) ? '' : $intNiveauRecursivite + 1;

Modifié par Anymah (05 Aug 2012 - 13:19)
Salut,


Ah oui merci beaucoup, je ne connaissais pas du tout, mais bon je ne trouve pas cette écriture logique !

Merci à vous !
Qu'est ce que tu ne trouves pas logique ? C'est tout à fait logique et très pratique. Et ça existe dans quasiment tous les langages (PHP, C/C++, Objective C, JavaScript, etc).


L'operateur ternaire renvoi toujours un résultat, la 1ere valeur si la condition est vérifiée, sinon la 2eme.

$resultat = condition ? valeur1 : valeur2;
Modifié par jb_gfx (05 Aug 2012 - 20:42)
Ben pour moi ça ne l'est pas...

Je trouve bizarre de commencer par écrire la variable qui est égale à la condition etc... enfin je trouve le sens bizarre, c'est tout ^^ Mais c'est une question d'habitude !
Ce n’est pas plus bizarre que ceci :
$i = $i + 1;

Utiliser le symbole d’égalité "=" pour ne pas désigner une égalité mais une affectation. Tant que l’on y est, pourquoi ne pas coder les additions avec le symbole "-".
Il y a plein de choses bizarres en programmation et le pire c’est que l’on s’y fait.
Modifié par adrien881 (06 Aug 2012 - 14:50)
Bref, chacun code comme il le souhaite, tant que ça marche...

C'est comme marquer

if (true === $foo && 1 === $bar) {

}


au lieu de

if (true === $foo && 1 === $bar) 
{

}
Pages :