OVH Cloud OVH Cloud

regroupper les valeurs doubles dans un tableau

6 réponses
Avatar
andrea.sparascio
Bonjour,

Voici mon problème j'ai fait un formulaire avec un champs texte qui me
permet dès l'envoie de celui-ci de créer un tableau en dissociant
chaques mots contenu et les afficher sous forme d'un tableau de 2
colonnes. Dans la première se trouve la clé sous la forme de chaques
mots dans l'orde alphabétique en ne tenant compte que des mots
suppérieur à 7 lettre et sur la deuxième colonne sa valeur numérique
remplacée par une expression régulière. Tout fonctionne mais mon
soucis est du moment où 2 mots (clé) différents mais ayant leurs
valeurs numérique identique dans le deuxième colonne. je souhaiterais
pouvoir les fusionner en une seule ligne avec dans la première colonne
les mots correspondant à la même valeur numérique séparé d'une virgule
et le numéro unique correspondant dans la deuxième colonne.
(pas facile d'être clair mais je fais de mon mieux)

Exemple:

dans le champs texte du formulaire j'envoie ceci:

"andrea patrick henri jonhatan christine emmanuelle christelle
emmanuel"

actuellement le résutat donne:

1ère colonne (clé) 2ème colonne (valeur)

CHRISTELLE 2474783
CHRISTINE 2474784
EMMANUEL 3662683
EMMANUELLE 3662683
JONHATAN 5664282
PATRICK 7287425

dans ma demande je souaihterais que l'on affiche de cette façon:

CHRISTELLE 2474783
CHRISTINE 2474784
EMMANUEL, EMMANUELLE 3662683
JONHATAN 5664282
PATRICK 7287425

dans cette exemple j'ai ce code:
/*ceci me permet de filtrer tous les caractères et symboles spéciaux,
d'enlever les doublons aux niveaux des mots et de convertir les mots
en la valeur numérique souhaitée le tout fusionné en un seul tableau
avec la fonction array_combine.*/

<?php
function array_combine($a1, $a2) {
if(count($a1) != count($a2))
return false;
if(count($a1) <= 0)
return false;
$a1 = array_values($a1);
$a2 = array_values($a2);
$output = array();
for($i = 0; $i < count($a1); $i++) {
$output[$a1[$i]] = $a2[$i];
}
return $output;
}
$donnee = strtoupper(strtr($nom,
'éèêàäâöôüûùçïî1234567890+*ç%&/()=?<>$£!,.;:-_"', 'eeeaaaoouuucii
'));
$clean = preg_replace('/\s+/', ' ', $donnee);
$nom = explode(' ', $clean);
$numero = explode(' ', strtr($clean, 'ABCDEFGHIJKLMNOPQRSTUVWXYZ',
'22233344455566677778889999'));
$tableau = array_combine($nom, $numero);
ksort($tableau);
?>

dans la page html j'ai ceci:

<table width="400" border="1">
<tr>
<td width="25" align="center"><h4>N&deg;</h4></td>
<td align="center"><h4>PRENOM</h4></td>
<td width="60" align="center"><h4>NUMERO</h4></td>
</tr>
<?php
$nombre = 1;
while ( list($key, $val) = each($tableau) ) {
if ( strlen($key) < 7 ) {
echo '';
}
else {
echo eval('?>' .
"<tr><td>&nbsp;<? echo $nombre; ?></td><td><p>&nbsp;<?
echo $key; ?></p></td><td><p>&nbsp;<? echo substr($val, 0, 7);
?></p></td></tr>" . '<?');
$nombre ++;
}
}
?>
</table>

Voilà pouvez-vous m'éclairer sachant que ce code n'est pas des plus
cleans vu que je ne suis pas un expert en programmation non plus mais
fait de mon mieux
;-)

Merci d'avance

6 réponses

Avatar
Jedi121
dans le champs texte du formulaire j'envoie ceci:
"andrea patrick henri jonhatan christine emmanuelle christelle
emmanuel"

dans ma demande je souaihterais que l'on affiche de cette façon:

CHRISTELLE 2474783
CHRISTINE 2474784
EMMANUEL, EMMANUELLE 3662683
JONHATAN 5664282
PATRICK 7287425

<?php
function array_combine($a1, $a2) {


Attention tu définis une fonction existante en PHP :
http://www.php.net/fr/array_combine

dans la page html j'ai ceci:
<?php
$nombre = 1;
while ( list($key, $val) = each($tableau) ) {
if ( strlen($key) < 7 ) {
echo '';


Cette ligne echo ''; ne sert à rien, tu peux l'enlever.

}
else {
echo eval('?>' .
"<tr><td>&nbsp;<? echo $nombre; ?></td><td><p>&nbsp;<?
echo $key; ?></p></td><td><p>&nbsp;<? echo substr($val, 0, 7);
?></p></td></tr>" . '<?');


Pas très beau ça, essaye une version plus simple :
echo
"<tr><td>&nbsp;$nombre</td><td><p>&nbsp;$key</p></td><td><p>&nbsp;".substr($val,0,7)."</p></td></tr>";
Et révise la façon dont PHP et HTML se mélangent :
pas besoin des "?>" en plus dans l'HTML, pas besoin des echo()...

Pour ta question initiale, il doit y avoir une solution élégante à base
de array_unique, array_reverse mais je ne l'ai pas.
Je pense que je parcourrai le tableau pour le faire élément par élément
mais c'est long.

Avatar
Jedi121
fazule vient de nous annoncer :
Je complète en modifiant ta fonction pour faire ce que tu veux :
J'interverti les clefs et les valeurs dans l'appel de la fonction.
On doit définir par une fonction utilisateur les fonctions utilisées
par array_walk() donc ne soit pas surpris des première déclarations.

<?php
function tronquer1(&$a) //on définit la fonction du array_walk();

qui supprime la virgule de tête
{
$a = substr($a,1);
}
function tronquer7(&$a) //on définit la fonction du array_walk();
qui tronque à 7 caractères
{
$a = substr($a,0,7);
}

function array_combine($a2, $a1) { //on interverti l'odre d'appel
pour échanger les numéros et les prénoms

if(count($a1) != count($a2))
return false;
if(count($a1) <= 0)
return false;
$a1 = array_values($a1);
$a2 = array_values($a2);
$output = array();
for($i = 0; $i < count($a1); $i++) {


$output[$a1[$i]] .= ",".$a2[$i]; //on concatène
les prénoms si le numéro est identique

}


array_walk($output,"tronquer1"); //on tronque la virgule de
début sur tous les prénoms
$output = array_flip($output); //on échnage les clefs et
les valeurs pour remttre le tableau dans le bon sens

return $output;
}
$donnee = strtoupper(strtr($nom,
'éèêàäâöôüûùçïî1234567890+*ç%&/()=?<>$£!,.;:-_"', 'eeeaaaoouuucii
'));
$clean = preg_replace('/s+/', ' ', $donnee);
$nom = explode(' ', $clean);
$numero = explode(' ', strtr($clean, 'ABCDEFGHIJKLMNOPQRSTUVWXYZ',
'22233344455566677778889999'));


array_walk($numero, "tronquer7"); //On tronque dès maintenant le
numéro à 7 caractères pour permettre les comparaisons plus tard.

$tableau = array_combine($nom, $numero);
ksort($tableau);
?>


Avatar
dmetzler
Il faut simplement inverser la manière de créer ton tableau. Tes
valeurs deviennent des clés et tes clés des valeurs.

En gros tu as besoin d'une fonction Name2Key qui à un nom associe ta
valeur.

Et puis ensuite tu fais :
$TAB ('andrea','patrick','henri','jonhatan','christine','emmanuelle','christelle',
'emmanuel');

foreach($TAB as $nom) {
$RESULT[Name2Key($nom)][] = $nom;
}

Le tableau $RESULT sera indexé par tes véritables clés et chaque
clé contiendra un tableau contenant les noms des personnes
Avatar
andrea.sparascio
Merci beaucoup pour votre aide ça m'a permi de résoudre le problème
facilement.

En ce qui concerne les mots doublons il n'y a pas vraiment du soucis
il suffit juste de les filtrers avant, de refaire un implode et de
traîter les noms par la suite.

Mais j'ai remarqué qu'un petit problème se pose car du moment où le
mots dépasse 12 caractère le numéro corespondant s'affiche dans le
tableau comme ceci:

6.12345678E+12

Un problème se pose du moment où l'on séléctionne les 7 première
chiffres il tiens compte du point comme caractère même en le filtrant
avec une expression régulière.

Est-il possible de prendre en compte dans un tableau par une fonction
le nombre entier correspondant du moment où il dépasse 12 chiffres?

Merci d'avance.
Avatar
andrea.sparascio
Jedi121 Dit:

function array_combine($a1, $a2) {


Attention tu définis une fonction existante en PHP :
http://www.php.net/fr/array_combine



Je sais mais elle n'est que valable qu'à partir de PHP 5 mais il est
vrai que j'aurai du la nommer différemment pour ne pas préter à
confusion.


Avatar
Olivier Miakinen

Mais j'ai remarqué qu'un petit problème se pose car du moment où le
mots dépasse 12 caractère le numéro corespondant s'affiche dans le
tableau comme ceci:

6.12345678E+12


C'est le problème des types flous de PHP. Ce qu'il faut, c'est empêcher
que la chaîne de caractères "612345678901" se transforme en entier
612345678901.

Je ne vois pas dans ton code d'endroit où cela peut se produire, si ce
n'est peut-être dans la fonction de tri ksort(). Une possibilité serait
alors de coder ta propre fonction de tri, mais c'est toujours bête de
réinventer la roue (surtout la roue carrée, car cela dégradera les
performances d'autant plus que le nombre de données est important. Et
puis finalement c'est peut-être array_values() qui joue des tours.

Une autre possibilité, plus simple, c'est que $numero ne commence jamais
par un chiffre tant que tu le manipules. Par exemple, remplacer :
strtr($clean, 'ABCDEFGHIJKLMNOPQRSTUVWXYZ',
'22233344455566677778889999')
par :
'N' . strtr($clean, 'ABCDEFGHIJKLMNOPQRSTUVWXYZ',
'22233344455566677778889999')
(sauf que ça ne marchera pas vu que tu as plusieurs numéros séparés par
des blancs, mais tu vois l'idée).

C'est seulement à la fin que tu vireras le 'N' initial par un substr()
ou un str_replace().


--
Olivier Miakinen
Non, monsieur le juge, je vous le jure : jamais je n'ai cité
Bruxelles dans ma signature.