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

EDI, CMS, Outils, Scripts et API PHP Discussion :

Parser PHP arbre phylogénétique type Newick


Sujet :

EDI, CMS, Outils, Scripts et API PHP

  1. #21
    Membre averti
    Profil pro
    Inscrit en
    Septembre 2009
    Messages
    46
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2009
    Messages : 46
    Par défaut
    Alors j'ai un peu bidouillé et on est bon maintenant

    Voilà le code d'appel :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    		$Newick = new $this->Newick(substr($file_content, 0, -1));
    		$TreeParse = $Newick->parse();
    et le résultat :

    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
    Array
    (
        [0] => Array
            (
                [6:0.84] => Array
                    (
                        [:0.59] => Array
                            (
                                [:0.05] => Array
                                    (
                                        [:0.05] => Array
                                            (
                                                [0] => 1:0.01
                                                [1] => 2:0.01
                                            )
     
                                        [:0.04] => Array
                                            (
                                                [0] => 5:0.02
                                                [1] => 19:0.02
                                            )
     
                                    )
     
                                [:0.08] => Array
                                    (
                                        [0] => 3:0.03
                                        [1] => 4:0.03
                                    )
     
                            )
     
                        [:0.57] => Array
                            (
                                [0] => 7:0.13
                                [1] => 20:0.13
                            )
     
                    )
     
            )
     
    )
    Maintenant, si tu veux toujours m'aider , il faudrait transformer l'array obtenu pour avoir une structure comme celle donnée précédemment et réécrite ci dessous. Ce avec quoi j'ai du mal c'est créer un code qui explore des array qui possèdent des profondeurs différentes en fonction de l'arbre qu'on va leur donner... tu vois ce que je veux dire ?


    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
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    Array(
    	[0] => Array (
    		[0] => Array (
    			[Nombre_Appreannts] => 9
    			[Distance] => 1.16
    			[id] => Array (
    				[0] => 1
    				[1] => 2
    				[2] => 5
    				[3] => 19
    				[4] => 3
    				[5] => 4
    				[6] => 6
    				[7] => 7
    				[8] => 20
    			)
    		)
    	) 
    	[1] => Array (
    		[0] => Array (
    			[Nombre_Appreannts] => 6
    			[Distance] => 0.19
    			[id] => Array (
    				[0] => 1
    				[1] => 2
    				[2] => 5
    				[3] => 19
    				[4] => 3
    				[5] => 4
    			)
    		)
    		[1] => Array (
    			[Nombre_Appreannts] => 3
    			[Distance] => 1.06
    			[id] => Array (
    				[0] => 6
    				[1] => 7
    				[2] => 20
    			)
    		)
    	) 
    	[2] => Array (
    		[0] => Array (
    			[Nombre_Appreannts] => 4
    			[Distance] => 0.06
    			[id] => Array (
    				[0] => 1
    				[1] => 2
    				[2] => 5
    				[3] => 19
    			)
    		)
    		[1] => Array (
    			[Nombre_Appreannts] => 2
    			[Distance] => 0.03
    			[id] => Array (
    				[0] => 3
    				[1] => 4
    			)
    		)
    		[2] => Array (
    			[Nombre_Appreannts] => 2
    			[Distance] => 0.13
    			[id] => Array (
    				[0] => 7
    				[1] => 20
    			)
    		)
    		[3] => Array (
    			[Nombre_Appreannts] => 1
    			[Distance] => Alone
    			[id] => Array (
    				[0] => 6
    			)
    		)
    	) 
    )

  2. #22
    Membre Expert
    Avatar de gene69
    Profil pro
    Inscrit en
    Janvier 2006
    Messages
    1 769
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations professionnelles :
    Secteur : High Tech - Produits et services télécom et Internet

    Informations forums :
    Inscription : Janvier 2006
    Messages : 1 769
    Par défaut
    ça ne me semble pas impossible, il faudra que tu m'explicites la conversion.

  3. #23
    Membre averti
    Profil pro
    Inscrit en
    Septembre 2009
    Messages
    46
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2009
    Messages : 46
    Par défaut
    Alors donc l'idée serait d'avoir une structure comme suit pour chaque niveau avec autant de tableau qu'il y a de groupes disponibles à ce niveau (cf image uploadé dans les messages précédents) :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    [0] => Array (
    			[Nombre_Appreannts] => XX
    			[Distance] => XX
    			[id] => Array (
    				[0] => XX
    				[1] => XX
    				[2] => XX
    				...
    			)
    		)
    Par exemple au niveau 1 on considère que l'on a tout le monde donc on aura un tableau et tous les id dans ce tableau. Au niveau 2 on a 2 groupes (dans le cas présent) donc 2 tableaux avec des id répartis dans chacun.

    Ce qui est difficile je pense c'est d'aller chercher tous les ID du niveau qui sont dans des sous sections du tableau...

    Pour la lecture du tableau on a trois cas de figure pour les clés de tableau :

    => Un chiffre, deux points une distance = ID d'élément seul

    => Une distance donc un groupe

    => Un chiffre seul = Un ID à récupérer

    Ca n'a pas l'air très clair quand je tente de l'expliquer... ^^

  4. #24
    Membre Expert
    Avatar de gene69
    Profil pro
    Inscrit en
    Janvier 2006
    Messages
    1 769
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations professionnelles :
    Secteur : High Tech - Produits et services télécom et Internet

    Informations forums :
    Inscription : Janvier 2006
    Messages : 1 769
    Par défaut
    dans ton example précédant, le premier neud de l'arbre reformaté présente une distance à 1.16. Comment est-elle calculée?

    je continue à lire et à poser des questions...

  5. #25
    Membre Expert
    Avatar de gene69
    Profil pro
    Inscrit en
    Janvier 2006
    Messages
    1 769
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations professionnelles :
    Secteur : High Tech - Produits et services télécom et Internet

    Informations forums :
    Inscription : Janvier 2006
    Messages : 1 769
    Par défaut
    en théorie une approche recursive et itérative sont équivalente, dans notre cas je pense que l'approche récursive sera plus instinctive.. on verra bien. Avec un peut de chance on pourra p'tre faire directement le bon arbre depuis Newik...

    ensuite, dans la version "reformatée" de l'arbre, les indices dans le tableau principal (racine), est ce que ça correspond à la profondeur du noeud dans la représentation de Newik ?

    le nombre d'apprenant c'est simple a obtenir au moment du retours d'un parcours "en profondeur". Idem pour la liste des fils.

    la distance, on verra ... tiens c'est quoi Alone?

    les groupes et les pas groupes.

    si j'ai bien compris c'est: "ID:distance"


    et comment tu as généré ton example? tu ne montres jamais ton code.... ça c'est malhonnête.

  6. #26
    Membre averti
    Profil pro
    Inscrit en
    Septembre 2009
    Messages
    46
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2009
    Messages : 46
    Par défaut
    Alors pour répondre à tes questions dans l'ordre :

    Dans l'exemple précédent la valeur était à 1.16 parce que j'avais mis ma matrice à jour. Pour repartir sur des bases commune, je mets en bas de ce message la dernière mise à jour de l'arbre et le résultat généré. Le calcul diffère en fonction de l’algorithme de clustering utilisé (éléments les plus proches, les plus éloignés, moyenne des éléments...ça dépend ^^).

    Pour ce qui est des indices, si j'ai bien compris la question, non ça ne correspond pas à la profondeur du noeud.

    Alone c'est juste moi qui avait écrit ça pour dire qu'il appartenait à aucun groupe mais effectivement, ca devrait pas être Alone mais 0.84 !

    Oui c'est IDistance mais la distance après les ID ne m'intéresse pas tant que ca. Celle ci correspond aux distances à l'intérieur du groupe. Ce qui m'intéresse ce sont les distances entre les groupes.

    Et pour l'exemple je l'ai écrit "à la main" ^^ Donc pas de code à montrer

  7. #27
    Membre Expert
    Avatar de gene69
    Profil pro
    Inscrit en
    Janvier 2006
    Messages
    1 769
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations professionnelles :
    Secteur : High Tech - Produits et services télécom et Internet

    Informations forums :
    Inscription : Janvier 2006
    Messages : 1 769
    Par défaut
    y manque la PJ

  8. #28
    Membre Expert
    Avatar de gene69
    Profil pro
    Inscrit en
    Janvier 2006
    Messages
    1 769
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations professionnelles :
    Secteur : High Tech - Produits et services télécom et Internet

    Informations forums :
    Inscription : Janvier 2006
    Messages : 1 769
    Par défaut
    alors si c'est pas la profondeur du noeud, c'est quoi cet indice?
    Est ce que c'est une entrée d'indice par groupe rencontré dans le parcours de l'arbre? dans ce cas pourquoi ya des regroupements dans le niveau immédiatement inférieur?

    [0] => 1:0.01

    => Un chiffre seul = Un ID à récupérer
    dans ma représentation [0] ça veux dire première feuille du noeud... je ne suis pas sur de ta réponse.

  9. #29
    Membre averti
    Profil pro
    Inscrit en
    Septembre 2009
    Messages
    46
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2009
    Messages : 46
    Par défaut
    Ah oui effectivement...alors que je m'étais dit de bien y faire attention...la semaine va être longue ^^

    L'arbre :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    (((((1:0.01,2:0.01):0.05,(5:0.02,19:0.02):0.04):0.05,(3:0.03,4:0.03):0.08):0.59,(7:0.13,20:0.13):0.57):0.14,6:0.84);
    Le rendu :
    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
    Array
    (
        [0] => Array
            (
                [6:0.84] => Array
                    (
                        [:0.59] => Array
                            (
                                [:0.05] => Array
                                    (
                                        [:0.05] => Array
                                            (
                                                [0] => 1:0.01
                                                [1] => 2:0.01
                                            )
     
                                        [:0.04] => Array
                                            (
                                                [0] => 5:0.02
                                                [1] => 19:0.02
                                            )
     
                                    )
     
                                [:0.08] => Array
                                    (
                                        [0] => 3:0.03
                                        [1] => 4:0.03
                                    )
     
                            )
     
                        [:0.57] => Array
                            (
                                [0] => 7:0.13
                                [1] => 20:0.13
                            )
     
                    )
     
            )
     
    )
    Pour le chiffre seul dans la clé ça veut dire que dans la valeur de la clé il y a un ID à récupérer. Il y a effectivement des éléments que l'on veut récupérer à la fois dans les clés mais aussi dans leur valeurs (pour les ID de plus bas niveau).



    Je viens de voir dans le tableau généré qu'il manquait le 0.14 qui regroupe tous les ID sauf le 6...Why not ?

  10. #30
    Membre Expert
    Avatar de gene69
    Profil pro
    Inscrit en
    Janvier 2006
    Messages
    1 769
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations professionnelles :
    Secteur : High Tech - Produits et services télécom et Internet

    Informations forums :
    Inscription : Janvier 2006
    Messages : 1 769
    Par défaut
    bonne question

  11. #31
    Membre Expert
    Avatar de gene69
    Profil pro
    Inscrit en
    Janvier 2006
    Messages
    1 769
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations professionnelles :
    Secteur : High Tech - Produits et services télécom et Internet

    Informations forums :
    Inscription : Janvier 2006
    Messages : 1 769
    Par défaut
    j'ai la réponse. les drapeaux étaient mal réinitialisés. ça simplifie le code.

    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
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    <?php
    $toto = '((((1:0.a1,2:a2)3:0.a3,((4:0.b1,5:0.b2)6:0.b3,(7:0.c1,8:0.c2)9:0.c3)10:0.bc3)11:0.abc3,(12:0.d1,13:0.d2):0.d3)14:0.abcd3,15:0.e2)';
    $toto ='((((1:0.01,2:0.01):0.05,(5:0.02,19:0.02):0.04):0.05,(3:0.03,4:0.03):0.08):0.59,(7:0.13,20:0.13):0.57):0.14,6:0.84)';
    $arbre = new Newik( $toto);
     
    echo '<pre>';
    print_r( $arbre->parse() );
     
     
    Class Newik {
     
    	protected $arbre;
    	private $position;
    	private $max_leng;
    	static $DEBUG = false;
     
    	function __construct($arbre){
    		$this->arbre = $arbre;
    		$this->init();
    	}
     
    	function init(){
    		$this->position=0;
    		$this->max_leng = strlen($this->arbre);
    	}
     
    	function debug($msg, $tampon, $flag){	
    		if ( self::$DEBUG )	{ 
    			echo $this->arbre,"\n";
    			$turing = str_repeat('.',$this->max_leng)."\n";
    			$turing[$this->position]= "^";
    			echo $turing;
    			echo $msg,' ',$this->arbre[$this->position],' position:',$this->position,' tampon:',$tampon,' flag:',$flag,"\n\n";
    		}
    	}
     
    	function appendChild(&$resultat, $flag,$tampon){
    		$this->debug('naming ', $tampon, $flag );
    		if ( $flag == 2 ){
    			$last = array_pop($resultat);
    			$resultat[$tampon]=$last;
    		}
    		else {
    			$resultat[]=$tampon;
    		}
     
    	}
     
    	function parse(){
    		$flagNomGroupe = 0; // a 2 lorsque ce qui suit peut être un nom de sous groupe.
    		$tampon = '';
    		$this->debug(' begin ', $tampon, $flagNomGroupe );
    		$resultat=array();
    		while( $this->position < $this->max_leng ){
    			$tmp = $this->arbre[$this->position]; 
    			if( $tmp == '(' ) {
    				$this->debug('open ', $tampon,$flagNomGroupe );
    				$this->position++;
    				$resultat[]= $this->parse(); //passage par référence! 
    				$flagNomGroupe = 1; //d'apres wikipedia, on peut avoir un nom de groupe apres une ), dans ce cas pas de ,
    			}
    			else if ($tmp == ')') {
    				//on a fini de lire le fils de droite
    				$this->debug('closing ', $tampon,$flagNomGroupe );
    				$this->appendChild($resultat, $flagNomGroupe, $tampon);
    				return $resultat; 
    			}
    			else if( $tmp == ',' ) {
    				// on a fini de lire le fils de gauche
    				$this->debug('inter ', $tampon,$flagNomGroupe );				
    				$this->appendChild($resultat, $flagNomGroupe, $tampon);
    				$flagNomGroupe = 0;
    				$tampon = '';
    			}
    			else {
    				$tampon .= $tmp;
    				if ( $flagNomGroupe == 1 ){
    					$flagNomGroupe = 2;
    				}
    			}
    			$this->position++;
    		}
    		// ne doit pas s'afficher.
    		return $resultat;
    	}
    }
    tu as des pistes pour la transformation du tableau?

  12. #32
    Membre averti
    Profil pro
    Inscrit en
    Septembre 2009
    Messages
    46
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2009
    Messages : 46
    Par défaut
    Super ca prends toutes les infos avec ton dernier code.

    Pour la transformation du tableau, j'ai commencé à écrire ça mais je suis coincé au moment ou il faut descendre dynamiquement dans les sous noeuds. Là j'avoue ne pas trop savoir comment le prendre....

    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
    function TreeOrganize ($Tree) {
     
    	$TreeOutput = array();
     
    	foreach ($Tree as $Tkey => $Tvalue) {
    		if (preg_match('/\:([0-9]*\.[0-9]+|[0-9]+)/', $Tkey)) { //Clé = Distance => Nouveau groupe
     
    //C'est ici qu'il faudrait rajouter une fonction de récursivité pour explorer tous les groupes je pense
     
    			$a = array(
    				'Apprenants' => '', //??
    				'Distance' => substr($Tkey, 1),
    				'ID' => array() //??
    			);
    			array_push($TreeOutput, $a);
    		} elseif (preg_match('/[0-9]+/', $Tkey)) { //Clé = Chiffre => ID seul
    			$data = explode(':', $Tvalue);
    			$a = array(
    				'Apprenants' => 1,
    				'Distance' => $data[1],
    				'ID' => array($data[0])
    			);
    			array_push($TreeOutput, $a);
    		}
    	}
     
    	return $TreeOutput;
    }
    Ce qui donne pour l'instant :

    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
    Array
    (
        [0] => Array
            (
                [Apprenants] => 
                [Distance] => 0.14
                [ID] => Array
                    (
                    )
     
            )
     
        [1] => Array
            (
                [Apprenants] => 1
                [Distance] => 0.84
                [ID] => Array
                    (
                        [0] => 6
                    )
     
            )
     
    )

  13. #33
    Membre Expert
    Avatar de gene69
    Profil pro
    Inscrit en
    Janvier 2006
    Messages
    1 769
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations professionnelles :
    Secteur : High Tech - Produits et services télécom et Internet

    Informations forums :
    Inscription : Janvier 2006
    Messages : 1 769
    Par défaut
    tu t'embetes pour rien !

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    //preg_match('/\:([0-9]*\.[0-9]+|[0-9]+)/', $Tkey);
    que tu peux remplacer par:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    $tab = explode(':',$Tkey);
    if( count($tab) == 2 ){
     $distance = $tab[1];
     if( empty($tab[0]) ) {
     
     }
     else{
     
     }
    }else {  //count == 1{
    }
    A mon avis c'est plus simple et plus performant. bn sinon ya p'tre plus simple... c'est pas très important pour l'instant.

    //C'est ici qu'il faudrait rajouter une fonction de récursivité pour explorer tous les groupes je pense
    l'avantage d'une fonction récursive c'est que c'est elle-meme !!! (mais parfois c'est bien pratique d'avoir une fonction différente pour appeler la récursivité. Dans la classe que j'ai utilisé, j'ai utilisé le constructeur pour faire les initialisations, comme ça j'ai tout près pour la fonction récursive.

    'ID' => array() //??
    tu remplaces ci dessus les points d’interrogations par les noeuds ($tab[] ) qui sont résultats de la fonction de récursion.

    'Apprenants' => '', //??
    c'est le count de 'ID' non ?

  14. #34
    Membre averti
    Profil pro
    Inscrit en
    Septembre 2009
    Messages
    46
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2009
    Messages : 46
    Par défaut
    Peut être qu’effectivement les recherches par expressions régulières sont plus gourmandes en ressources...Mais ca semblait plus propre ^^

    'Apprenants' est bien un count de ID.

    Mais je t'avoue que j'ai du mal à imaginer la fonction récursive sans qu'elle tourne en boucle...

    Sachant qu'en plus au premier niveau on est censé tout avoir...ca je l'ai pas intégré dans ma fonction...le résultat obtenu commence pour l'instant au deuxième niveau directement...

  15. #35
    Membre Expert
    Avatar de gene69
    Profil pro
    Inscrit en
    Janvier 2006
    Messages
    1 769
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations professionnelles :
    Secteur : High Tech - Produits et services télécom et Internet

    Informations forums :
    Inscription : Janvier 2006
    Messages : 1 769
    Par défaut
    qu'est ce que t'en pense?
    bon je te laisse coder.

    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
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    <?php
    $toto = '((((1:0.a1,2:a2)3:0.a3,((4:0.b1,5:0.b2)6:0.b3,(7:0.c1,8:0.c2)9:0.c3)10:0.bc3)11:0.abc3,(12:0.d1,13:0.d2):0.d3)14:0.abcd3,15:0.e2)';
    $toto ='((((1:0.01,2:0.01):0.05,(5:0.02,19:0.02):0.04):0.05,(3:0.03,4:0.03):0.08):0.59,(7:0.13,20:0.13):0.57):0.14,6:0.84)';
    $arbre = new Newik( $toto);
     
    echo '<pre>';
    print_r( $arbre->parse() );
    print_r( $arbre->showGroups() );
     
    Class Newik {
     
    	protected $arbre;
    	private $position;
    	private $max_leng;
    	private $groupes;
    	static $DEBUG = false;
     
    	function __construct($arbre){
    		$this->arbre = $arbre;
    		$this->init();
    	}
     
    	function init(){
    		$this->position=0;
    		$this->max_leng = strlen($this->arbre);
    	}
     
    	function debug($msg, $tampon, $flag){	
    		if ( self::$DEBUG )	{ 
    			echo $this->arbre,"\n";
    			$turing = str_repeat('.',$this->max_leng)."\n";
    			$turing[$this->position]= "^";
    			echo $turing;
    			echo $msg,' ',$this->arbre[$this->position],' position:',$this->position,' tampon:',$tampon,' flag:',$flag,"\n\n";
    		}
    	}
     
    	function appendChild(&$resultat, $flag,$tampon){
    		$this->debug('naming ', $tampon, $flag );
    		if ( $flag == 2 ){
    			$last = array_pop($resultat);
    			$resultat[$tampon]=$last;
    		}
    		else {
    			$resultat[]=$tampon;
    		}
     
    	}
     
    	function parse(){
    		$flagNomGroupe = 0; // a 2 lorsque ce qui suit peut être un nom de sous groupe.
    		$tampon = '';
    		$this->debug(' begin ', $tampon, $flagNomGroupe );
    		$resultat=array();
    		while( $this->position < $this->max_leng ){
    			$tmp = $this->arbre[$this->position]; 
    			if( $tmp == '(' ) {
    				$this->debug('open ', $tampon,$flagNomGroupe );
    				$this->position++;
    				$resultat[]= $this->parse(); //passage par référence! 
    				$flagNomGroupe = 1; //d'apres wikipedia, on peut avoir un nom de groupe apres une ), dans ce cas pas de ,
    			}
    			else if ($tmp == ')') {
    				//on a fini de lire le fils de droite
    				$this->debug('closing ', $tampon,$flagNomGroupe );
    				$this->appendChild($resultat, $flagNomGroupe, $tampon);
    				return $resultat; 
    			}
    			else if( $tmp == ',' ) {
    				// on a fini de lire le fils de gauche
    				$this->debug('inter ', $tampon,$flagNomGroupe );				
    				$this->appendChild($resultat, $flagNomGroupe, $tampon);
    				$flagNomGroupe = 0;
    				$tampon = '';
    			}
    			else {
    				$tampon .= $tmp;
    				if ( $flagNomGroupe == 1 ){
    					$flagNomGroupe = 2;
    				}
    			}
    			$this->position++;
    		}
    		// ne doit pas s'afficher.
    		return $resultat;
    	}
     
     
     
     
    	function showGroups(){
    		$this->init();
    		$arbre = $this->parse();
    		$this->groupes = array(); //c'est pourquoi c'est privé.
    		$this->readGroups($arbre);
    		return $this->groupes;
    	}
     
     
    	private function readGroups( $racine ){
    		$feuillage = array(); // la liste de toute les feuilles issue d'une racine !
    		if ( is_array($racine) ) {
    			// on n'est pas sur une feuille
    			foreach (  $racine as $tronc => $branches ){
    				//echo 'tronc = ', $tronc,"\n";
    				$feuilles =	$this->readGroups( $branches );
    				// d'abord on prépare ceci.
    				$feuillage = array_merge($feuillage, $feuilles);
    				// ensuite, chaque fois qu'on a autre chose qu'un noeud non nommé qui a un nom non automatique
    				// il se trouve que les noms "automatiques" sont des entiers alors que les noms explicites des chaines...
    				if ( is_string( $tronc) )$this->registerGroup($tronc, $feuilles);
    			}
    		}
    		else {
    			//on est sur une feuille, 
    			// on ajoute une feuille et rien d'autre a faire !
    			$feuillage[]=self::readID($racine);//ici c'est pas vraiment une branche, c'est une feuille.
    		}
    		return $feuillage;
    	}
     
    	//protected pour autoriser la dérivation ...	
    	static protected function readID($string){
    		$tab = explode(':',$string,2);
    		return $tab[0]; 
    	}
     
     
    	//protected pour autoriser la dérivation ...
    	protected function registerGroup($clee, $feuilles){
    		//print('registering '.$clee."\n");
    		$tab = explode(':',$clee,2);
    		if( count($tab) == 2 ){
    			$distance = $tab[1];
    			if( empty($tab[0]) ) {
    				$nom = 'Anonymous';
    			}
    			else{
    				$nom = $tab[0];
    			}
    		}else {  //count == 1{
    			$distance = 'Unknown';
    			$nom = 'Anonymous';
    		}
     
    		$this->groupes[]= array(
    			'Nom'=> $nom,
    			'Apprenants' => count($feuilles), //??
    			'Distance' => $distance,
    			'ID' => $feuilles );//??		
    	}
    }

  16. #36
    Membre averti
    Profil pro
    Inscrit en
    Septembre 2009
    Messages
    46
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2009
    Messages : 46
    Par défaut
    Ah là on commence à s'approcher dangereusement de ce qu'il me faut

    Juste la clé "Nom", c'est pour quoi ? J'ai lancé la fonction avec et sans, ça n'a rien changé.

    Juste deux remarques :

    - l'ID 6 n'est pas pris en compte
    - la représentation par niveau non plus

    Un niveau pourrait comprendre plusieurs groupes en fonction de l'arbre avec obligatoirement au niveau 1, 1 groupe contenant tous les ID.
    Ici au niveau 2, on aurait 2 groupes : celui du 6 tout seul et le dernier actuellement retourné par la fonction et contenant 8 ID.

    Ce qui donnerait pour les deux premiers niveaux par exemple :

    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
    47
    48
    49
    50
    Array
    (
        [0] => Array ( //Niveau 1
            [0] => Array //Groupe
                (
                    [Apprenants] => 9
                    [Distance] =>
                    [ID] => Array
                        (
                            [0] => 1
                            [1] => 2
                            [2] => 5
                            [3] => 19
                            [4] => 3
                            [5] => 4
                            [6] => 7
                            [7] => 20
                            [8] => 6
                        )
                )
        )
        [1] => Array ( //Niveau 2
            [0] => Array //Groupe
                (
                    [Apprenants] => 1
                    [Distance] => 0.84
                    [ID] => Array
                        (
                            [0] => 6
                        )
                )
            [1] => Array //Groupe
                (
                    [Apprenants] => 8
                    [Distance] => 0.14
                    [ID] => Array
                        (
                            [0] => 1
                            [1] => 2
                            [2] => 5
                            [3] => 19
                            [4] => 3
                            [5] => 4
                            [6] => 7
                            [7] => 20
                        )
     
                )
        )
    )

  17. #37
    Membre Expert
    Avatar de gene69
    Profil pro
    Inscrit en
    Janvier 2006
    Messages
    1 769
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations professionnelles :
    Secteur : High Tech - Produits et services télécom et Internet

    Informations forums :
    Inscription : Janvier 2006
    Messages : 1 769
    Par défaut
    la clée "Nom" ? dans le tableau résultat ?

    tu pourrais très bien avoir une représentation newik du genre

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    (element:distance,element:distance)nomGroupe:distanceGroupe;
    Nom => nomGroupe

    pour toi ça ne te sert à rien... bon suffit de l'enlever... en plus ça simplifie... (je viens de voir que c'est tjr Anonymous, mais si tu eleves le test de la ligne 111, tu vois tous les noeuds et ça change.)

    et j'ai mis Newik->groupes sur 1 seul étage parce que tu m'as dis que l'indice de premier niveau n'était pas la profondeur du groupe.... et maintenant tu me redis le contraire ... je te laisse cherche un peu.

    faut modifier un ptit peut pour lui dire le niveau de récursion au moment du rappel récursif. et changer les noms de fonction, des variables en français, des méthodes en anglais... pfff

  18. #38
    Membre Expert
    Avatar de gene69
    Profil pro
    Inscrit en
    Janvier 2006
    Messages
    1 769
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations professionnelles :
    Secteur : High Tech - Produits et services télécom et Internet

    Informations forums :
    Inscription : Janvier 2006
    Messages : 1 769
    Par défaut
    Dans mon code, l'id 6 n'est pas pris en compte parce qu'il est dans un groupe "anonyme".

    essaie avec:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    $toto ='((((1:0.01,2:0.01):0.05,(5:0.02,19:0.02):0.04):0.05,(3:0.03,4:0.03):0.08):0.59,(7:0.13,20:0.13):0.57):0.14,6:0.84)tout:0';

  19. #39
    Membre Expert
    Avatar de gene69
    Profil pro
    Inscrit en
    Janvier 2006
    Messages
    1 769
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations professionnelles :
    Secteur : High Tech - Produits et services télécom et Internet

    Informations forums :
    Inscription : Janvier 2006
    Messages : 1 769
    Par défaut
    en fait y avait 3 problèmes,
    1. l'arbre de newick n'était pas juste syntaxiquement, mais je ne générais pas d'exception... et je ne vois pas trop comment générer une exception en cas de ',' finale ou parenthèse manquante sans rajouter un flag supplémentaire.
    2. il ne prenais pas en compte le nom du groupe "racine", maintenant c'est possible avec en plus la gestion du ";" qui me semble un peu moins inutile (mais inutile quand même)
    3. le groupe principal n'était pas nommé => donc ignoré (by design, won't fix)


    donc vala la Xe version du code.
    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
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
     
    <?php
    $toto ='(((((1:0.01,2:0.01):0.05,(5:0.02,19:0.02):0.04):0.05,(3:0.03,4:0.03):0.08):0.59,(7:0.13,20:0.13):0.57):0.14,6:0.84)tout:distance;'; //";" optionnel
    $arbre = new Newik( $toto);
     
    echo '<pre>';
    print_r( $arbre->parse() );
    print_r( $arbre->showGroups() );
     
    Class Newik {
     
    	protected $arbre;
    	private $position;
    	private $max_leng;
    	private $groupes;
    	static $DEBUG = false;
     
    	function __construct($arbre){
    		$this->arbre = $arbre;
    		$this->init();
    	}
     
    	function init(){
    		$this->position=0;
    		$this->max_leng = strlen($this->arbre);
    	}
     
    	function debug($msg, $tampon, $flag){	
    		if ( self::$DEBUG )	{ 
    			echo $this->arbre,"\n";
    			$turing = str_repeat('.',$this->max_leng)."\n";
    			$turing[$this->position]= "^";
    			echo $turing;
    			echo $msg,' ',$this->arbre[$this->position],' position:',$this->position,' tampon:',$tampon,' flag:',$flag,"\n\n";
    		}
    	}
     
    	function appendChild(&$resultat, $flag,$tampon){
    		$this->debug('naming ', $tampon, $flag );
    		if ( $flag == 2 ){
    			$last = array_pop($resultat);
    			$resultat[$tampon]=$last;
    		}
    		else {
    			$resultat[]=$tampon;
    		}
     
    	}
     
    	function parse(){
    		$flagNomGroupe = 0; // a 2 lorsque ce qui suit peut être un nom de sous groupe.
    		$tampon = '';
    		$this->debug(' begin ', $tampon, $flagNomGroupe );
    		$resultat=array();
    		while( $this->position < $this->max_leng ){
    			$tmp = $this->arbre[$this->position]; 
    			if( $tmp == '(' ) {
    				//$this->debug('open ', $tampon,$flagNomGroupe );
    				$this->position++;
    				$resultat[]= $this->parse(); //passage par référence! 
    				$flagNomGroupe = 1; //d'apres wikipedia, on peut avoir un nom de groupe apres une ), dans ce cas pas de ,
    			}
    			else if ($tmp == ')') {
    				//on a fini de lire le fils de droite
    				//$this->debug('closing ', $tampon,$flagNomGroupe );
    				$this->appendChild($resultat, $flagNomGroupe, $tampon);
    				return $resultat; 
    			}
    			else if( $tmp == ',' ) {
    				// on a fini de lire le fils de gauche
    				//$this->debug('inter ', $tampon,$flagNomGroupe );				
    				$this->appendChild($resultat, $flagNomGroupe, $tampon);
    				$flagNomGroupe = 0;
    				$tampon = '';
    			}
    			else if ( $tmp == ';' ){
    				$this->debug('break ', $tampon,$flagNomGroupe );
    				break;
    			}
    			else {
    				$tampon .= $tmp;
    				if ( $flagNomGroupe == 1 ){
    					$flagNomGroupe = 2;
    				}
    			}
    			$this->position++;
    		}
    		//finalisation
    		if ( $flagNomGroupe == 2 ){
    			return array( $tampon =>$resultat );
    		}
    		return $resultat;
    	}
     
     
     
     
    	function showGroups(){
    		$this->init();
    		$arbre = $this->parse();
    		$this->groupes = array(); //c'est pourquoi c'est privé.
    		$this->readGroups($arbre);
    		return $this->groupes;
    	}
     
     
    	private function readGroups( $racine ){
    		$feuillage = array(); // la liste de toute les feuilles issue d'une racine !
    		if ( is_array($racine) ) {
    			// on n'est pas sur une feuille
    			foreach (  $racine as $tronc => $branches ){
    				//echo 'tronc = ', $tronc,"\n";
    				$feuilles =	$this->readGroups( $branches );
    				// d'abord on prépare ceci.
    				$feuillage = array_merge($feuillage, $feuilles);
    				// ensuite, chaque fois qu'on a autre chose qu'un noeud non nommé qui a un nom non automatique
    				// il se trouve que les noms "automatiques" sont des entiers alors que les noms explicites des chaines...
    				if ( is_string( $tronc) )$this->registerGroup($tronc, $feuilles);
    			}
    		}
    		else {
    			//on est sur une feuille, 
    			// on ajoute une feuille et rien d'autre a faire !
    			$feuillage[]=self::readID($racine);//ici c'est pas vraiment une branche, c'est une feuille.
    		}
    		return $feuillage;
    	}
     
    	//protected pour autoriser la dérivation ...	
    	static protected function readID($string){
    		$tab = explode(':',$string,2);
    		return $tab[0]; 
    	}
     
     
    	//protected pour autoriser la dérivation ...
    	protected function registerGroup($clee, $feuilles){
    		//print('registering '.$clee."\n");
    		$tab = explode(':',$clee,2);
    		if( count($tab) == 2 ){
    			$distance = $tab[1];
    			if( empty($tab[0]) ) {
    				$nom = 'Anonymous';
    			}
    			else{
    				$nom = $tab[0];
    			}
    		}else {  //count == 1{
    			$distance = 'Unknown';
    			$nom = 'Anonymous';
    		}
     
    		$this->groupes[]= array(
    			'Nom'=> $nom,
    			'Apprenants' => count($feuilles), //??
    			'Distance' => $distance,
    			'ID' => $feuilles );//??		
    	}
    }

  20. #40
    Membre Expert
    Avatar de gene69
    Profil pro
    Inscrit en
    Janvier 2006
    Messages
    1 769
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations professionnelles :
    Secteur : High Tech - Produits et services télécom et Internet

    Informations forums :
    Inscription : Janvier 2006
    Messages : 1 769
    Par défaut
    bon j'ai fait mieux.

Discussions similaires

  1. [Web Service] PHP, soap et type complex
    Par Invité dans le forum Bibliothèques et frameworks
    Réponses: 1
    Dernier message: 01/07/2009, 17h58
  2. [Web Service][nuSOAP] génération wsdl avec php et les types
    Par ybvj59930 dans le forum Bibliothèques et frameworks
    Réponses: 2
    Dernier message: 06/02/2009, 17h03
  3. Parser une variable de type XML
    Par demcoul dans le forum Format d'échange (XML, JSON...)
    Réponses: 5
    Dernier message: 12/11/2008, 12h34
  4. [XPATH] parser un fichier de type rss 1.0
    Par samplaid dans le forum Format d'échange (XML, JSON...)
    Réponses: 1
    Dernier message: 07/05/2008, 22h46
  5. parser PHP
    Par tomy29 dans le forum EDI, CMS, Outils, Scripts et API
    Réponses: 6
    Dernier message: 11/01/2006, 11h01

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