IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Langage PHP Discussion :

Recursivite & parent [PHP 5.2]


Sujet :

Langage PHP

  1. #1
    Nouveau membre du Club
    Inscrit en
    Juin 2004
    Messages
    42
    Détails du profil
    Informations forums :
    Inscription : Juin 2004
    Messages : 42
    Points : 32
    Points
    32
    Par défaut Recursivite & parent
    Bonjour,

    Je cherche à déterminer le niveau d'un élément.

    Je récupère les données issues d'un fichier .csv

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    if(($handle = fopen($file, 'r')) !== FALSE) {
      while(($data = fgetcsv($handle, 1000, ';')) !== FALSE) {
              $arr[] = $data;
      }
    }
    $arr ressemble à :
    [0] =>
          [0]=>ID
          [1]=>'MON LABEL'
          [2]=>PARENT_ID
    [1] =>
          [0]=>ID
          [1]=>'MON LABEL'
          [2]=>PARENT_ID
    Je parviens à déterminer le niveau 0. ([2]=='').
    Par contre je ne parviens pas a construire la fonction récursive afin d'obtenir les niveaux des objets restants.

    Le but étant de générer un nouveau fichier csv en sortie classé par niveau (du 0 à n).

    Mis à part faire des boucles sans fin je bloque un peu.

    Merci d'avance pour votre aide.

  2. #2
    Membre expérimenté
    Homme Profil pro
    Inscrit en
    Septembre 2009
    Messages
    875
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 34
    Localisation : France, Isère (Rhône Alpes)

    Informations forums :
    Inscription : Septembre 2009
    Messages : 875
    Points : 1 313
    Points
    1 313
    Par défaut
    Tu entends quoi par niveau 0?
    Je trouve ca étrange de parler de récursivité et de parent/enfant en parlant d'un tableau imbriqué ^^'

  3. #3
    Nouveau membre du Club
    Inscrit en
    Juin 2004
    Messages
    42
    Détails du profil
    Informations forums :
    Inscription : Juin 2004
    Messages : 42
    Points : 32
    Points
    32
    Par défaut
    Merci pour ta réponse.
    Par niveau 0 j'entends l'objet qui n'a pas de parent. Cet objet (comme tous les autres) peut avoir n enfants.
    Le tableau je le construit à partir de la lecture d'un fichier csv.
    Un exemple de données dans le csv :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    ID;LABEL;PARENT_ID;
    1 ; toto ; 2 ;
    2 ; titi   ;    ;
    3 ; tata ; 2 ;   
    4 ; tutu ; 3 ;
    Suite lecture csv je construit ce tableau
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
     
    [0] =>
          [0]=>1
          [1]=>toto
          [2]=>2
    [1] =>
          [0]=>2
          [1]=>titi
          [2]=>
    [2] =>
          [0]=>3
          [1]=>tata
          [2]=>2
    [3] =>
          [0]=>4
          [1]=>tutu
          [2]=>3
    Je ne sais pas si c'est plus clair à présent.
    L'objectif étant d'importer ces objets dans une base sachant que pour importer un enfant il est nécessaire d'avoir le parent (relation).
    Dans l'exemple ci dessus pour insérer "tutu" je dois insérer "titi" puis "tata"
    Merci.

  4. #4
    Membre expérimenté
    Homme Profil pro
    Inscrit en
    Septembre 2009
    Messages
    875
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 34
    Localisation : France, Isère (Rhône Alpes)

    Informations forums :
    Inscription : Septembre 2009
    Messages : 875
    Points : 1 313
    Points
    1 313
    Par défaut
    Je vois pas comment tu vas t'en sortir avec un tableau :/

    je pense que manipuler des objets avec des méthode getPere/GetFils serait peut etre mieux, ne serait ce pour l’évolutivité et la maintenabilité de ton code.

    Attend quand même d'avoir d'autres retours de développeurs.

    Parcontre si le seul problème que t'as c'est la rentrée en base de données, peut être que le plus simple c'est de faire un algo qui trie ton tableau afin d'avoir le père en premier, les fils niveau 1 etc.. qui suivent, afin de ne pas avoir d'erreur de clé.
    Voir juste désactiver les contraintes de clé étrangère le temps de l'insertion (bouh c'est crado mais tellement économique )

  5. #5
    Expert éminent sénior
    Avatar de rawsrc
    Homme Profil pro
    Dev indep
    Inscrit en
    Mars 2004
    Messages
    6 142
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 48
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Dev indep

    Informations forums :
    Inscription : Mars 2004
    Messages : 6 142
    Points : 16 545
    Points
    16 545
    Billets dans le blog
    12
    Par défaut
    Salut,

    Citation Envoyé par tininou Voir le message
    L'objectif étant d'importer ces objets dans une base sachant que pour importer un enfant il est nécessaire d'avoir le parent (relation).
    Dans l'exemple ci dessus pour insérer "tutu" je dois insérer "titi" puis "tata"
    Merci.
    Dans ce cas, il faut que tu revoies ton algo de manière à avoir en sortie un tableau à 2 dimensions avec pour clés la liste des id parent séparés par un tiret (par exemple)

    Quelque chose comme ça :
    array(
        '2-0' => 'toto',
        '2-1' => 'titi',
        '2-3' => 'tata',
        '2-3-4' => 'tutu'
    )
    Une piste mais il va te falloir quelques fonctions supplémentaires pour triturer ce tableau
    Une fois obtenu, tu fais un simple tri et tu as l'ordre dans lequel insérer tes données.

  6. #6
    Nouveau membre du Club
    Inscrit en
    Juin 2004
    Messages
    42
    Détails du profil
    Informations forums :
    Inscription : Juin 2004
    Messages : 42
    Points : 32
    Points
    32
    Par défaut
    Merci pour vos réponses...

    J'ai un peu avancé....

    j'ai trouvé une fonction récursive :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    function makeParentChildRelations(&$inArray, &$outArray, $currentParentId = 0, ) {
        if(!is_array($inArray)) {
            return;
        }
        if(!is_array($outArray)) {
            return;
        }
        foreach($inArray as $key => $tuple) {
            if($tuple['parentId'] == $currentParentId) {
                $tuple['children'] = array();
                makeParentChildRelations($inArray, $tuple['children'], $tuple['id']);
                $outArray[$tuple['id']] = $tuple;
            }
        }
    }
    Cela à l'air de fonctionner j'obtiens un array de ce type à présent :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    [1] =>
          ['id']=>2
          ['name']=>titi
          ['parentId']=>
          ['children'] =>
                [0] =>
                      ['id']=>1
                      ['name']=>toto
                      ['parentId']=>2
     
                [1] =>
                      ['id']=>3
                      ['name']=>tata
                      ['parentId]=>2
    .....
    Toutefois je ne vois pas comment utiliser ce tableau pour avoir les enfants avant les parents. Où alors comment modifier la fonction récursive pour ajouter une notion de profondeur( niveau) des enfants et trier le tableau dessus) ?

    Je sèche un peu.

  7. #7
    Expert éminent sénior
    Avatar de rawsrc
    Homme Profil pro
    Dev indep
    Inscrit en
    Mars 2004
    Messages
    6 142
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 48
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Dev indep

    Informations forums :
    Inscription : Mars 2004
    Messages : 6 142
    Points : 16 545
    Points
    16 545
    Billets dans le blog
    12
    Par défaut
    Citation Envoyé par tininou Voir le message
    Le but étant de générer un nouveau fichier csv en sortie classé par niveau (du 0 à n).
    Pourrais-tu mettre le fichier résultat attendu pour l'exemple que tu as pris.

  8. #8
    Nouveau membre du Club
    Inscrit en
    Juin 2004
    Messages
    42
    Détails du profil
    Informations forums :
    Inscription : Juin 2004
    Messages : 42
    Points : 32
    Points
    32
    Par défaut
    Pour que cela soit clair (car je ne sais pas si je n'ai pas tout mélanger dans mes explication précédentes), a partir d'un fichier source :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    id;name;parentId
    1;tata;2
    2;toto;;
    3;tutu;2;
    4;titi;1;
    Il faudrait que en sortie j'ai un fichier csv de ce type :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    id;name;parentId
    2;toto;;
    1;tata;2
    3;tutu;2
    4;titi;1
    l'ordre des id 1 et 3 n'est pas important car l'id n°2 (le parent) est avant.


    D'autres infos diverses pouvant peut-être aider car je me complique peut etre la vie et vous oriente vers de mauvaises pistes :
    Le nombre d'enfants n'est pas connu à l'avance.
    Le fichier source est assez volumineux (22000 lignes).
    Ces fichiers sont destinés à être importer via un outil propriétaire. Je ne maitrise pas l'accès à la base derrière.
    La seule contrainte est de créer le nœud le plus haut afin de ne pas avoir d'échec lors de la création de l'enfant. L'outil à besoin de la structure complète (parent1/parent2/parent3/..../objet).

  9. #9
    Expert éminent sénior
    Avatar de rawsrc
    Homme Profil pro
    Dev indep
    Inscrit en
    Mars 2004
    Messages
    6 142
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 48
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Dev indep

    Informations forums :
    Inscription : Mars 2004
    Messages : 6 142
    Points : 16 545
    Points
    16 545
    Billets dans le blog
    12
    Par défaut
    Ok, rien n'empêche d'extrapoler un peu et d'arriver au même résultat en se facilitant la vie.

    Est ce que ça irait si sur le tableau initial récupéré, on faisait un simple array_multisort() sur parent_id croissant ?
    Ainsi on aurait au début du csv tous les nœuds racine (sans parent) et ensuite on aurait forcément les nœuds enfants dans le bon ordre avec la certitude que leur nœud parent a déjà été créé.

    Si c'est ok, je te propose ceci :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
     
    $source = array(
        array('1', 'toto', '2'),
        array('2', 'titi', ''),
        array('3', 'tata', '2'),
        array('4', 'tutu', '3')
    );
     
    foreach ($source as $v)
    {
        $parent_id[] = $v[2];
    }
     
    array_multisort($parent_id, SORT_NUMERIC, $source);

  10. #10
    Nouveau membre du Club
    Inscrit en
    Juin 2004
    Messages
    42
    Détails du profil
    Informations forums :
    Inscription : Juin 2004
    Messages : 42
    Points : 32
    Points
    32
    Par défaut
    La simplicité ca me plait....
    Mais sans que je comprenne pourquoi cela n'a pas l'air de marcher. (problème de dimension dans le tableau ?)

    J'ai effectivement bien les objets sans parent en premier par contre après j'ai des enfants avant leur parent.

  11. #11
    Expert éminent sénior
    Avatar de rawsrc
    Homme Profil pro
    Dev indep
    Inscrit en
    Mars 2004
    Messages
    6 142
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 48
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Dev indep

    Informations forums :
    Inscription : Mars 2004
    Messages : 6 142
    Points : 16 545
    Points
    16 545
    Billets dans le blog
    12
    Par défaut
    la question fondamentale est : est ce que les enfants ont toujours un id supérieur à celui de leur parent ?

  12. #12
    Nouveau membre du Club
    Inscrit en
    Juin 2004
    Messages
    42
    Détails du profil
    Informations forums :
    Inscription : Juin 2004
    Messages : 42
    Points : 32
    Points
    32
    Par défaut
    Non, un enfant peut avoir un id inférieur à un parent.

  13. #13
    Expert éminent sénior
    Avatar de rawsrc
    Homme Profil pro
    Dev indep
    Inscrit en
    Mars 2004
    Messages
    6 142
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 48
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Dev indep

    Informations forums :
    Inscription : Mars 2004
    Messages : 6 142
    Points : 16 545
    Points
    16 545
    Billets dans le blog
    12
    Par défaut
    ah purée

    alors on va ruser, c'est pas 2 ids qui vont nous casser les c... quand même.

    Sur combien de digits au maximum tes ids peuvent s'étaler ?

  14. #14
    Nouveau membre du Club
    Inscrit en
    Juin 2004
    Messages
    42
    Détails du profil
    Informations forums :
    Inscription : Juin 2004
    Messages : 42
    Points : 32
    Points
    32
    Par défaut
    En fait ils ont toujours 5 digits

  15. #15
    Nouveau membre du Club
    Inscrit en
    Juin 2004
    Messages
    42
    Détails du profil
    Informations forums :
    Inscription : Juin 2004
    Messages : 42
    Points : 32
    Points
    32
    Par défaut
    Allez c'est bon je m'en suis (presque) sorti avec le récursif :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
     
    function makeParentChildRelations(&$inArray, &$outArray, $currentParentId = 0) {
        if(!is_array($inArray)) {
            return;
        }
        if(!is_array($outArray)) {
            return;
        }
        foreach($inArray as $key => $tuple) {
            if($tuple['parentId'] == $currentParentId) {
                $tuple['children'] = array();
                makeParentChildRelations($inArray, $tuple['children'], $tuple['id']);
                $outArray[$tuple['id']] = $tuple;
            }
        }
    }
     
    function traverseArray($array,&$compt=0,&$wrt,&$Arroutput){
     
    	foreach($array as $key=>$value){
    		if(is_array($value)){
    				traverseArray($value,$compt,$wrt,$Arroutput);
    			}
    		else{
     
    			if($compt<2){
    				$wrt[] = $value;
    				$compt++;
    			}
    			else{
    				$wrt[]= $value;
     
    				$Arroutput[] = $wrt;
     
     
    				$compt=0;
    				$wrt=array();
     
    			}
     
    			//echo $key." = ".$value."<br />\n";
    		}
     
    	}
     
    }
    compteur me sert juste à reconstruire chaque objet

    un fputcsv et le tour est joué...

    Merci pour votre aide et votre patience à essayer de trouver une solution à ce problème qui m'aura mis un bon mal de crane

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Iteration VS recursivité
    Par yacinechaouche dans le forum C
    Réponses: 40
    Dernier message: 16/11/2012, 11h52
  2. Comment reloader la frame parent?
    Par mythtvtalk.com dans le forum ASP
    Réponses: 3
    Dernier message: 27/08/2003, 11h40
  3. Conception d'une classe parente
    Par VincentB dans le forum Langage
    Réponses: 9
    Dernier message: 24/06/2003, 17h28
  4. DLL, affichage et parent...
    Par KRis dans le forum Composants VCL
    Réponses: 6
    Dernier message: 13/12/2002, 17h01

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo