Besoin d'aide pour un algo

Résolu/Fermé
0z0z Messages postés 108 Date d'inscription mardi 9 février 2010 Statut Membre Dernière intervention 18 mai 2010 - 17 févr. 2010 à 16:08
0z0z Messages postés 108 Date d'inscription mardi 9 février 2010 Statut Membre Dernière intervention 18 mai 2010 - 18 févr. 2010 à 16:36
Bonjour à tous,

J'ai un site en PHP dans le quel j'ai un tableau dont les données proviennent d'un fichier CSV.
Dans ce tableau j'affiche une liste d'article qui doit être fabriqué. Et il est très probable qu'un même article doivent être fabriqué plusieurs fois.
$lesColonnes[26] représente la quantité du produit.
$lesColonnes[22] représente la référence du produit.
Ce que je voudrais c'est rassembler les produits qui ont la même référence et faire un +1 pour la quantité.

J'avais penser faire un truc du genre :


echo "<table border='1'>\n";
$nb = 0;
while(!feof($fp)) {
    $nb++;
    echo "<tr>";
    $j = sizeof($ligne);
    // On récupère une ligne
    $Ligne = fgets($fp,1024);
    $lesColonnes = explode(";", $Ligne);
    $lesColonnes = str_replace('"','',$lesColonnes);
    $date = date("d/m/Y");
    if ($lesColonnes[17] >= $date){
       if ($lesColonnes[22].[$nb] = $lesColonnes[22].[$nb-1]) {
          // On affiche la ligne
          echo "<td>$lesColonnes[23]</td>";
          echo "<td>$lesColonnes[22]</td>";
          echo "<td>$lesColonnes[24]</td>";
          echo "<td>$lesColonnes[25]</td>";
          echo "<td>$lesColonnes[26]</td>";
          echo "<td>$lesColonnes[17]</td>";
          echo "</tr>";
       }
    }
}
echo "</table>\n";





Ligne 2 et 13 c'est ce que j'ai rajouté mais qui ne fonctionne pas biensur. Donc si vous avez une petite idée je suis preneuse. Merci.

37 réponses

Defouille Messages postés 388 Date d'inscription mercredi 13 janvier 2010 Statut Membre Dernière intervention 15 novembre 2011 54
17 févr. 2010 à 16:21
Bonjour,

Si j'ai bien compris, tu peux faire une boucle pour préparer un tableau compacter qui aura le format que tu souhaite :

$lesColonnes_compact = array();
foreach($lesColonnes as $t)
{
	if(isset($lesColonnes_compact[$t[22]])
		$lesColonnes_compact[$t[22]][26]++;
	else
		$lesColonnes_compact[$t[22]]=$t;
}


Dis moi si ce n'est pas ça que tu cherches, mais c'est ce que j'ai compris.
0
0z0z Messages postés 108 Date d'inscription mardi 9 février 2010 Statut Membre Dernière intervention 18 mai 2010 5
17 févr. 2010 à 16:35
Bon en gros avec ce code :

$file = "...\nomFichier.csv";
$contenu = fopen ($file, "r") or die("Cannot open $file");
if (!$fp = fopen($file,"r")) {
echo "Echec de l'ouverture du fichier";
exit;
}
else {
	echo "<table border='1'>\n";
	while(!feof($fp)) {
		echo "<tr>";
		$j = sizeof($ligne);
		// On récupère une ligne
		$Ligne = fgets($fp,1024);
		$lesColonnes = explode(";", $Ligne);
		$lesColonnes = str_replace('"','',$lesColonnes);
		$date = date("d/m/Y");
		if ($lesColonnes[17] >= $date {
			// On affiche la ligne
			echo "<td>$lesColonnes[23]</td>";
			echo "<td>$lesColonnes[22]</td>";
			echo "<td>$lesColonnes[24]</td>";
			echo "<td>$lesColonnes[25]</td>";
			echo "<td>$lesColonnes[26]</td>";
			echo "<td>$lesColonnes[17]</td>";
			echo "</tr>";
		}
	}
	echo "</table>\n";
	fclose($fp);
}


J'obtiens un tabelau du genre :

nom_prod ; ref_prod ; quantité ; date
ex1 ; 001 ; 1 ; 18/02/10
ex1 ; 001 ; 1 ; 18/02/10
ex1 ; 001 ; 2 ; 25/02/10
ex2 ; 002 ; 1 ; 18/02/10


En gros je veux que mes deux première ligne deviennent :
ex1 ; 001 ; 2 ; 18/02/10
car elles on la même référence ainsi que la même date.


J'espère que mon explication est assez claire :/
0
Blocks Messages postés 98 Date d'inscription mardi 28 juillet 2009 Statut Membre Dernière intervention 31 janvier 2011 3
17 févr. 2010 à 16:51
J'écris une réponse (je préviens car ca prends du temps U.u)
0
0z0z Messages postés 108 Date d'inscription mardi 9 février 2010 Statut Membre Dernière intervention 18 mai 2010 5
17 févr. 2010 à 16:55
Merci de prévenir :)
J'attend ^^
0

Vous n’avez pas trouvé la réponse que vous recherchez ?

Posez votre question
Defouille Messages postés 388 Date d'inscription mercredi 13 janvier 2010 Statut Membre Dernière intervention 15 novembre 2011 54
17 févr. 2010 à 17:04
Ca ne fonctionne pas ce que je t'ai donné ? j'ai l'impression que ca correspond bien à ce que tu veux faire, il faut juste que tu ajoutes le bout de code avant la création de ton table, et que tu utilises la variable $lesColonnes_compact pour la création de ton table.
0
0z0z Messages postés 108 Date d'inscription mardi 9 février 2010 Statut Membre Dernière intervention 18 mai 2010 5
17 févr. 2010 à 17:14
echo "<table border='1'>\n";
	while(!feof($fp)) {
		$lesColonnes_compact = array();
		echo "<tr>";
		$j = sizeof($ligne);
		// On récupère une ligne
		$Ligne = fgets($fp,1024);
		$lesColonnes = explode(";", $Ligne);
		$lesColonnes = str_replace('"','',$lesColonnes);
		$date = date("d/m/Y");
		if ($lesColonnes[17] >= $date){
			foreach($lesColonnes as $l) {
				if(isset($lesColonnes_compact[$l[22]])
					$lesColonnes_compact[$l[22]][26]++;
				else
					$lesColonnes_compact[$l[22]]=$l;
			}
			// On affiche la ligne
			echo "<td>$lesColonnes_compact[23]</td>";
			echo "<td>$lesColonnes_compact[22]</td>";
			echo "<td>$lesColonnes_compact[24]</td>";
			echo "<td>$lesColonnes_compact[25]</td>";
			echo "<td>$lesColonnes_compact[26]</td>";
			echo "<td>$lesColonnes_compact[17]</td>";
			echo "</tr>";
		}
	}
echo "</table>\n";


Est-ce bien ce que tu me propose ?
Si c'est le cas voici le message d'erreur :
<br />
<b>Parse error</b>: syntax error, unexpected T_VARIABLE in <b>maPage.php</b> on line <b>28</b><br />

l.28 = $lesColonnes_compact[$l[22]][26]++;
0
Blocks Messages postés 98 Date d'inscription mardi 28 juillet 2009 Statut Membre Dernière intervention 31 janvier 2011 3
17 févr. 2010 à 17:20
Déjà je suis pas sur que cela fonctionne dans tous les cas :
$lesColonnes[17] >= $date

Comparer deux chaines de caractère c'est pas l'idéal, puis en plus tu réutilise la fonction date à chaque fois, ce qui est une perte de temps (négligeable j'avoue). Tu pourrais le faire qu'une fois au début, bref

Pour faire ce que tu veux, avant d'afficher les données extraites du fichier CSV, tu dois les enregistrer et les pré-traiter. donc :


$file = "...\nomFichier.csv";
$contenu = fopen ($file, "r") or die("Cannot open $file");
if (!$fp = fopen($file,"r")) {
echo "Echec de l'ouverture du fichier";
exit;
}
else {
	$conteneur = Array();
	$date = date("d/m/Y");
	while(!feof($fp)) {
		$ligne = fgets($fp,1024);
		$colonne = explode(";", $ligne);
		$colonne = str_replace('"','',$colonne);
		if ($colonne[17] >= $date { // à corriger je suppose
			$conteneur[] = Array(
				$colonne[23], // 0
				$colonne[22], // 1 référence
				$colonne[24], // 2
				$colonne[25], // 3
				$colonne[26], // 4 quantité
				$colonne[17] // 5
			);
			// là j'ai toutes les données dans un tableau
		}
	}
	fclose($fp);
	$passe = Array(); // tableau pour mettre les références déjà passées
	
	echo "<table border='1'>\n";
	
	foreach ($conteneur as $colonne1) {
		$actuel = $colonne1[1];
		if (!in_array($actuel, $passe)) {
			$quantite = 0;
			foreach ($conteneur as $colonne2) {
				if ($colonne2[1] == $actuel)
					$quantite += $colonne2[4];
			}
			echo "<tr>";
			for ($i = 0; $i<6; $i++) {
				echo "<td>$colonne1[$i]</td>";
			}
			echo "</tr>";
			$passe[] = $actuel;
		}
	}
	echo "</table>\n";
}


Voilà qui est fait, a part petite négligence, ca devrait fonctionner. Par contre, pour la comparaison de date à corriger, je te suggère de repasser ca en timestamp pour comparer, ou même mieux, de stocker les timestamp directement dans le fichier CSV.

Edit : Il y avait une petite négligence -_-'
0
0z0z Messages postés 108 Date d'inscription mardi 9 février 2010 Statut Membre Dernière intervention 18 mai 2010 5
18 févr. 2010 à 10:14
Et voilà j'ai trouvé une autre négligence (juste un oubli de fermer une parenthèse).
Du coup maintenant ca marche. Enfin ca m'affiche bien chaque produit une seule fois.
Mais la quantité est toujours à 1... :S
0
Defouille Messages postés 388 Date d'inscription mercredi 13 janvier 2010 Statut Membre Dernière intervention 15 novembre 2011 54
17 févr. 2010 à 17:23
Non, en fait j'avais pas vu comment tu remplissais ton tableau, ma solution s'applique si tu as un tableau avec toute les lignes que tu veux afficher :

// Recupération des colonnes dans un tableau
while(!feof($fp)) {
		$lesColonnes_compact = array();
		echo "<tr>";
		$j = sizeof($ligne);
		// On récupère une ligne
		$Ligne = fgets($fp,1024);
		$lesColonnes = str_replace('"','',$Ligne);
		$lesColonnes[] = explode(";", $lesColonnes);
}

// Compactage des colonnes
foreach($lesColonnes as $t) {
	if(isset($lesColonnes_compact[$t[22]])
		$lesColonnes_compact[$t[22]][26]++;
	else
		$lesColonnes_compact[$t[22]]=$t;
}

// Affichage du tableau
echo "<table border='1'>\n";
foreach($lesColonnes_compact as $c)
{
	$date = date("d/m/Y");
	if ($c[17] >= $date)
	{
		// On affiche la ligne
		echo "<td>$c[23]</td>";
		echo "<td>$c[22]</td>";
		echo "<td>$c[24]</td>";
		echo "<td>$c[25]</td>";
		echo "<td>$c[26]</td>";
		echo "<td>$c[17]</td>";
		echo "</tr>";
	}
}
echo "</table>\n";


Ca devrait être mieux ^^
0
0z0z Messages postés 108 Date d'inscription mardi 9 février 2010 Statut Membre Dernière intervention 18 mai 2010 5
18 févr. 2010 à 09:50
Il y a une chose qui me semble un peu bizarre ici. Tu ouvres la balise <tr> avant d'avoir ouvert la balise <table> ...
0
Blocks Messages postés 98 Date d'inscription mardi 28 juillet 2009 Statut Membre Dernière intervention 31 janvier 2011 3
17 févr. 2010 à 17:31
Moi j'aimerais bien savoir, c'est quoi ce truc de fou ?

foreach($lesColonnes as $t) {
if(isset($lesColonnes_compact[$t[22]])
$lesColonnes_compact[$t[22]][26]++;
else
$lesColonnes_compact[$t[22]]=$t;
}

ZOOM : [$t[22]]

(Par rapport à mon code, j'aurais pu économiser de la mémoire en vérifiant directement lors de la récupération de données depuis le fichier si j'avais déjà vu la référence, avec un autre système)
(Enfin je dis ca, ca sert à rien, mais puisque on est dans l'algorithmique, ...)
0
0z0z Messages postés 108 Date d'inscription mardi 9 février 2010 Statut Membre Dernière intervention 18 mai 2010 5
17 févr. 2010 à 17:34
J'ai testé les deux solutions très rapidement mais apparement il y a un problème à chaque fois.

Defouille : il me met encore la même erreur pour $lesColonnes_compact[$l[22]][26]++;
Blocks : le problème survient à la sortie du while

Je dois quitter le bureau pour aujourd'hui mais je regarderai ca de plus près demain. Je vous remercie tout les deux.
0
Blocks Messages postés 98 Date d'inscription mardi 28 juillet 2009 Statut Membre Dernière intervention 31 janvier 2011 3
17 févr. 2010 à 17:49
Ok Defouille je vois ce que tu as voulu faire. Joli d'ailleurs le tableau associatif

Juste ca :

foreach($lesColonnes_compact as $c)

Faudrait l'adapter à un tableau associatif, de même que le reste

Et Ozoz, dans ton message, tu as écrit ca :
$lesColonnes_compact[$l[22]][26]++

ZOOM X2 : $l[22]][26]
ZOOM X4 : $l

C'est pas un "l" dans le code de Defouille -_-...

Pour Ozoz, j'ai édité mon code après, peut-être l'as tu utilisé quand il était faux :/.
0
0z0z Messages postés 108 Date d'inscription mardi 9 février 2010 Statut Membre Dernière intervention 18 mai 2010 5
18 févr. 2010 à 09:20
Bonjour Blocks et Defouille.
Ce matin j'ai rééssayer les codes que vous m'avez fournit hier mais j'ai toujours les mêmes erreurs.

Blocks :
C'est pas un "l" dans le code de Defouille -_-...
J'avais des "l" partout au lieu des "t" donc ca n'était pas un soucis mais j'ai quand même essayé avec "t" et j'ai la même erreur.
Pour la solution que tu as édité l'erreur est toujours au même au endroit. C'est-à-dire à la fermeture du while " }; ".
0
0z0z Messages postés 108 Date d'inscription mardi 9 février 2010 Statut Membre Dernière intervention 18 mai 2010 5
18 févr. 2010 à 10:49
Bon et bien j'ai trouvé une solution. Je vous l'expose :

$file = "...\nomFichier.csv";
$contenu = fopen ($file, "r") or die("Cannot open $file");
if (!$fp = fopen($file,"r")) {
	echo "Echec de l'ouverture du fichier";
}
else {
	$conteneur = Array();
	$date = '17/02/10';
	$resultats = array();
	while(!feof($fp)) {
  		// On récupère une ligne
  		$colonnes = fgetcsv($fp, 1024, ';');
  		if ($colonnes[17] >= $date){
		    // on indexe les résultats sur la reference
    		if (isset($resultats[$colonnes[22]])) {
				//si le produit est déjà référencé on ajoute la quantité à la quantité existante
      			$resultats[$colonnes[22]]['quantite'] += $colonnes[26];
    		}
    		else {
	      		//sinon on crée la ligne pour le produit
      			$resultats[$colonnes[22]] = array('rayon-ref' => $colonnes[23], 'codif-acheteur' => $colonnes[22], 
      			'codif-fournisseur' => $colonnes[24], 'libelle' => $colonnes[25], 'quantite' => $colonnes[26],
      			'date' => $colonnes[17]);
    		}
  		}
	}
 
	//on affiche les résultats
	echo '<table border=1>';
	foreach ($resultats as $ligne) {
  		echo '<tr>'
    	.'<td>'.$ligne['rayon-ref'].'</td>'
    	.'<td>'.$ligne['codif-acheteur'].'</td>'
    	.'<td>'.$ligne['codif-fournisseur'].'</td>'
    	.'<td>'.$ligne['libelle'].'</td>'
    	.'<td>'.$ligne['quantite'].'</td>'
    	.'<td>'.$ligne['date'].'</td>'
    	.'</tr>';
	}
	echo '</table>';
}	



Blocks je suis quand même intéressée par ta solution donc si tu vois d'où vient le problème j'aimerai bien savoir aussi :)
0
0z0z Messages postés 108 Date d'inscription mardi 9 février 2010 Statut Membre Dernière intervention 18 mai 2010 5
18 févr. 2010 à 11:03
Ah je viens de refaire des tests et enfaite il s'avère que ma solution n'est pas tout à fait optimiser.
Quand un même produit est a fabriquer pour deux dates différentes il me les rassemble. Or moi je veux bien distinguer les dates de fabrication :/
0
Blocks Messages postés 98 Date d'inscription mardi 28 juillet 2009 Statut Membre Dernière intervention 31 janvier 2011 3
18 févr. 2010 à 11:18
Donc si je comprends bien, bah besoin d'algorithme ? :')
0
0z0z Messages postés 108 Date d'inscription mardi 9 février 2010 Statut Membre Dernière intervention 18 mai 2010 5
18 févr. 2010 à 11:20
Bah enfaite celui que j'ai a un tout petit problème.
Donc si ta solution pouvais m'éviter ce problème ou bien si tu vois d'où vient mon problème ca serait parfait :)
0
Blocks Messages postés 98 Date d'inscription mardi 28 juillet 2009 Statut Membre Dernière intervention 31 janvier 2011 3
18 févr. 2010 à 12:58
Quand un même produit est a fabriquer pour deux dates différentes il me les rassemble. Or moi je veux bien distinguer les dates de fabrication :/

Ha d'accord ... Je viens de comprendre

Tu as ca :
RFGJ 28/03/10 1
RFGJ 22/04/10 2
RFGJ 22/04/10 1
RFGJ 22/04/10 1
RFHD 12/03/10 1

Et tu veux que ca devienne :

RFGJ 28/03/10 1
RFGJ 22/04/10 4
RFHD 12/03/10 1

?
Donc séparer par la référence, ET les dates ?
PS : Je voudrais aussi juste savoir si le système de comparaison des dates fonctionnes
car en gros tu dis :
si : "12/05/10" < "21/07/09" et donc c'est un peu n'importe quoi (sur un mois tu dois pas voir le problème, mais sur plusieurs mois tu auras des bugs je suppose)
0
0z0z Messages postés 108 Date d'inscription mardi 9 février 2010 Statut Membre Dernière intervention 18 mai 2010 5
18 févr. 2010 à 13:41
Pour être exacte j'ai ca :

Référence Quantité Expé au + tard
L0023 18 11/03/10
L0015 22 11/03/10
L0007 8 11/03/10

Et je voudrais avoir ca :

Référence Quantité Expé au + tard
L0023 9 11/03/10
L0007 8 11/03/10
L0015 5 11/03/10
L0023 9 18/03/10
L0015 17 18/03/10

Enfaite si la référence est la même, il me les rassemble à la date au plus tôt. Et moi je ne veux pas qu'il me les rassemble mais qui me les laisse bien distinct.
Vois tu ce que je veux dire ?

Pour la comparaison des dates pour l'instant tout ce fait sur un seul mois. Je n'ai pas eu l'occasion de faire le test pour quand il y a plusieurs mois. Que proposerais tu pour arranger cela ?
0
Blocks Messages postés 98 Date d'inscription mardi 28 juillet 2009 Statut Membre Dernière intervention 31 janvier 2011 3
18 févr. 2010 à 14:09
Un instant je vais essayer de l'améliorer et de trouver la faille (je peux pas vraiment l'essayer puisque j'ai pas de fichier CSV sous la main :p)

EDIT : Message 11 :
Faudrait l'adapter à un tableau associatif, de même que le reste
Je corrige, Defouille, ta syntaxe est bonne, je regarderais la prochaine fois (quoi que tu n'as même pas protesté U.u)
0
0z0z Messages postés 108 Date d'inscription mardi 9 février 2010 Statut Membre Dernière intervention 18 mai 2010 5
18 févr. 2010 à 14:27
Je t'ai créé un petit fichier CSV si tu veux pouvoir faire des tests...
Comment puis-je te l'envoyer ? Si tu en as besoin biensur.
0