Algorithme à la con, manipulation de chaines de caracteres

EDIT dans les commentaires, Ben propose une solution en une ligne de code avec une regex:D

J'ai une base de donnée mal foutue (spamoi qui l'ai conçue) dans laquelle les noms et prénoms sont dans le même champs. Une typographie est respectée, toutes les lettres du nom sont en majuscules tandis que seule la première lettre de chaque prénom l'est. Plus dur, il n'y a pas de tiret, les noms ou prénoms composés sont séparés par des espaces.

Dans la base de données contenant plus d'un millier d’identités, il n'est jamais arrivé qu'un nom de famille ait trois composantes. Maximum deux. C'est pour ça que par flegme je me suis arrêté à cette possibilité dans l'algo ci dessous.

C'est la quatrième fois en 3 ans que je suis amené à travailler sur une passerelle où cette mauvaise conception me gonfle fortement.

  • la première fois, en java, compilé, j'ai paumé la source du truc.
  • Refait en Vb6 pareil, pareil, un code de moins de 50 lignes, on se fiche un peu de devoir le refaire.
  • Refait en vb6 cette fois, j'ai retrouvé la source
  • Là c'est en php que ça m'intéresse de le faire.

Ça n'a pas trop d’intérêt mais comme ce n'est peut être pas la dernière fois que j'ai à me pencher sur ce problème, je garde les algos sur ce blog:

En PHP

  1. function separenomprenom($stringname)
  2. {
  3. /*
  4. *NomPac
  5.   * Il est sous cette forme: 'NOM Prenom' voire
  6.   * 'NOM COMPOSE Prenom' ou encore
  7.   * 'NOM Prenom composé'
  8.   *On va spliter les espaces. Si on obtient deux champs on est dans le cas 1
  9.   *pour distinguer les autres cas on va tester la deuxième lettre
  10.   *pour savoir si elle est en majuscules.
  11. */
  12. $nomexplode=explode(" ",$stringname);
  13. if (count($nomexplode)==2)
  14. { //NOM Prénom
  15. return array('nom'=>$nomexplode[0],'prenom'=>$nomexplode[1]);
  16. }
  17. else
  18. {
  19. //test sur la deuxieme lettre du second mot
  20. if(preg_match_all('/[A-Z]/', substr($nomexplode[1],1,1),$res)==1)
  21. { //NOM NOM2 Prénom
  22. $prenom="";
  23. for($i=2; $i<count($nomexplode)+1;$i++)
  24. {
  25. $prenom = $prenom.$nomexplode[$i]." ";
  26. }
  27. return array('nom'=>$nomexplode[0]." ".$nomexplode[1],'prenom'=>$prenom);
  28. }
  29. else
  30. { //NOM Prénom Prénom2
  31. $prenom="";
  32. for($i=1; $i<count($nomexplode)+1;$i++)
  33. {
  34. $prenom = $prenom.$nomexplode[$i]." ";
  35. return array('nom'=>$nomexplode[0],'prenom'=>$prenom);
  36. }
  37. }
  38. }
  39. }

En basic

J'ai testé le script php sur plusieurs centaines de noms, mais pas le basic que je viens de modifier pour qu'il soit lisible retiré du script global (il peut y avoir une erreur qui traine).

  1. 'NomPac
  2. ' Il est sous cette forme: 'NOM Prenom' voire
  3. ' 'NOM COMPOSE Prenom' ou encore
  4. 'NOM Prenom composé'
  5. 'On va spliter les espaces. Si on obtient deux champs on est dans le cas 1
  6. 'pour distinguer les autres cas on va tester la deuxième lettre
  7. 'pour savoir si elle est en majuscules.
  8.  
  9.  
  10. nomsplit() = Split(NomPac, " ")
  11. If UBound(nomsplit(), 1) = 1 Then
  12. 'nom Prénom
  13. nom = nomsplit(0)
  14. prenom= nomsplit(1)
  15. Else
  16. 'test sur la deuxieme lettre du second mot
  17. If Asc(Mid(nomsplit(1), 2, 1)) < 91 Then 'c'est une majuscule donc la suite du nom de famille
  18. nom = nomsplit(0) & " " & nomsplit(1)
  19. prenom = ""
  20. For i = 2 To UBound(nomsplit(), 1)
  21. prenom = prenom & nomsplit(i) & " "
  22. Next i
  23. Else
  24. nom = nomsplit(0)
  25. prenom =""
  26. For i = 2 To UBound(nomsplit(), 1)
  27. prenom = prenom & nomsplit(i) & " "
  28. Next i
  29. End If
  30. End If

Commentaires

1. Le mardi, décembre 7 2010, 21:19 par Ben

J'étais sur que ça passerai en une regex ...

($nom, $prenom) = /((?:[A-Z]{2}\w+\s?)+)\s(.+)/;

T'en dis quoi ?

2. Le mardi, décembre 7 2010, 22:56 par gnieark

Yeah trop génial, merci!!!! je teste dès demain

J'ai du mal avec les regex, faut que je me choppe des exos tout betement là dessus.

Page top