come codificare i dati del genitore / figli, struttura in JSON

Sto lavorando con d3.js per visualizzare le famiglie di animali (organismi) (fino a 4000 alla volta) come un grafo ad albero, se l’origine dati può essere un elenco di directory o di un elenco di namespace oggetti. i miei dati si presenta come:

json = {
    organisms:[
        {name: 'Hemiptera.Miridae.Kanakamiris'},
        {name: 'Hemiptera.Miridae.Neophloeobia.incisa'},
        {name: 'Lepidoptera.Nymphalidae.Ephinephile.rawnsleyi'},
        ... etc ...
    ]
}

la mia domanda è: sto cercando di trovare il modo migliore per convertire i dati di cui sopra per il gerarchica genitore /figli struttura dati è utilizzato da un certo numero di d3 visualizzazioni come diagramma ad albero (per esempio dati di vedere flare.json il d3/esempi/dati/directory).
Qui è un esempio di struttura dati richiesta:

{"name": "ROOT",
 "children": [
        {"name": "Hemiptera",
         "children": [
             {"name": "Miridae",
              "children": [
                  {"name": "Kanakamiris", "children":[]},
                  {"name": "Neophloeobia",
                   "children": [
                       {"name": "incisa", "children":[] }
                   ]}
              ]}
         ]},
        {"name": "Lepidoptera",
         "children": [
             {"name": "Nymphalidae",
              "children": [
                  {"name": "Ephinephile",
                   "children": [
                       {"name": "rawnsleyi", "children":[] }
                   ]}
              ]}
         ]}
    ]}
}

EDIT: chiuso tutte originali desiderato struttura di dati all’interno di un ROOT nodo, in modo conforme con la struttura della d3 esempi, che sono solo una master nodo padre.

Sto cercando di capire un generale modello di progettazione, e, come bonus, mi piacerebbe vedere alcune soluzioni in javascript, php, (o anche python). javascript è la mia preferenza.
Con riferimento a php: i dati in realtà sto usando proviene da una chiamata a un database da uno script php che consente di codificare i risultati json.
i risultati del database in php script è una matrice ordinata (vedi sotto) se che qualsiasi uso del php risposte.

Array
(
    [0] => Array
        (
            ['Rank_Order'] => 'Hemiptera'
            ['Rank_Family'] => 'Miridae'
            ['Rank_Genus'] => 'Kanakamiris'
            ['Rank_Species'] => ''
        ) ........

dove:
'Rank_Order' isParentOf 'Rank_Family' isParentOf 'Rank_Genus' isParentOf 'Rank_Species'

Ho chiesto una simile domanda, imperniato su una soluzione php qui, ma l’unica risposta è che non funziona sul mio server, e io non riesco a capire che cosa sta succedendo, quindi vorrei chiedere a questa domanda da un modello di progettazione di una prospettiva e di riferimento per il mio uso effettivo che è in javascript e d3.js.

  • Si potrebbe utilizzare una compressa in più la sintassi i.stack.imgur.com/V5zg0.jpg
  • Dalla tua descrizione sembra che questo sarebbe meglio fare lato server al momento i dati sono estratti dal DB. Il tuo desiderato struttura dovrebbe avere le parentesi quadre [] invece di ultraperiferiche parentesi graffe {} perché si sta usando come un array non è un oggetto. (Si noti, inoltre, non stai parlando di JSON qui, si sta parlando di oggetti JS. Stai serialising i dati JSON per ottenere per il cliente, ma la manipolazione che si desidera fare è dopo il JSON è stato analizzato in un JS oggetto.)
  • e @nnnnnn desiderato datastructure / sintassi sto cercando di partita è la struttura utilizzata in d3 esempi in modo che io non devo modificare tale libreria. questa libreria che utilizza le chiavi name e children. @nnnnnn hai ragione, avrei dovuto usare le parentesi quadre sul ultraperiferiche, ma questo mi ha fatto capire che ho bisogno di aggiungere un livello al di sopra del quale ho chiamata root invece di avere la struttura esistente, come i bambini, in modo da essere conformi al d3 treemap biblioteca. vorrei modificare l’esempio ‘struttura desiderata’
  • ho fatto la modifica, in modo che la struttura è contenuta come figli di un ROOT nodo, e quindi sto ancora utilizzando le parentesi graffe su ultraperiferiche. ancora una volta, questo è perché voglio usare la d3, biblioteca è
  • puoi descrivere un modo per convertire l’iniziale ‘piatto’ di dati per il vostro ‘nested’ struttura dell’array in javascript o php ? per rendere le cose più compresso è un buon consiglio, però !
  • questo stack overflow domanda mi sta dando un po ‘ di comprensione, ma non abbastanza

InformationsquelleAutor johowie | 2012-08-26

 

3 Replies
  1. 7

    Il seguente è specifico per la struttura che ci hai fornito, potrebbe essere reso più generico abbastanza facilmente. Sono sicuro che il addChild funzione può essere semplificata. Speriamo che i commenti sono utili.

    function toHeirarchy(obj) {
    
      //Get the organisms array
      var orgName, orgNames = obj.organisms;
    
      //Make root object
      var root = {name:'ROOT', children:[]};
    
      //For each organism, get the name parts
      for (var i=0, iLen=orgNames.length; i<iLen; i++) {
        orgName = orgNames[i].name.split('.');
    
        //Start from root.children
        children = root.children;
    
        //For each part of name, get child if already have it
        //or add new object and child if not
        for (var j=0, jLen=orgName.length; j<jLen; j++) {
          children = addChild(children, orgName[j]);      
        }
      }
      return root;
    
      //Helper function, iterates over children looking for 
      //name. If found, returns its child array, otherwise adds a new
      //child object and child array and returns it.
      function addChild(children, name) {
    
        //Look for name in children
        for (var i=0, iLen=children.length; i<iLen; i++) {
    
          //If find name, return its child array
          if (children[i].name == name) {
            return children[i].children;        
          }
        }
        //If didn't find name, add a new object and 
        //return its child array
        children.push({'name': name, 'children':[]});
        return children[children.length - 1].children;
      }
    }
    • confrontare la tua soluzione con quella da @nnnnnn (solo con 400 organismi e 4 livelli di classificazione) non sembra essere più veloce (circa 2x). la differenza tra questa soluzione e che da nnnnnn è il modo in cui stringhe di lunghezza zero sono trattati. questa soluzione renderà i nodi figlio per quelle di lunghezza zero nomi, sia lungo il ramo e ‘leaf’ nodi, mentre, nnnnnn non creare figli di lunghezza zero nomi, e anche di troncare il ‘ramo’ se c’è uno zero di nome di lunghezza lungo il ‘percorso/ramo’. Ovviamente non ho mai specificato il comportamento desiderato per questo caso ! +1 per la risposta
    • Comportamento per le stringhe di lunghezza zero è un artefatto (ho il sospetto nnnnnn è troppo), avrei pensato che non erano validi. Se si dovrebbe avere un comportamento specifico, si deve indicare e in che modo potrebbero verificarsi nei dati originali.
    • Sì, sono d’accordo e così stringhe di lunghezza zero sarà invalidato o curati prima di arrivare a questo punto.Per chiunque sia interessato nel mio data-source, anche io sono campi come ‘Rank_super famiglia’, che è opzionale, e alcune voci con nessun ‘Rank_Species’ come mostrato nell’esempio di dati. Tutte queste stringhe di lunghezza zero sara ‘scomparso’
    • btw è il RobG soluzione che sembra essere più veloce rispetto alla nnnnnn soluzione (solo su prove iniziali)
  2. 5

    Data di partenza di input credo che qualcosa di simile al codice riportato di seguito verrà produrre l’output desiderato. Non immagino questa è la più bella di un modo per farlo, ma è quello che è venuto in mente al momento.

    Sembrava più semplice per pre-elaborare i dati prima di dividere l’array iniziale di una stringa in un array di array come questo:

    [
       ["Hemiptera","Miridae","Kanakamiris" ],
       ["Hemiptera","Miridae","Neophloeobia","incisa" ],
       //etc
    ]

    …e poi il processo che per ottenere un lavoro oggetto in una forma qualcosa di simile a questo:

      working = {
           Hemiptera : {
               Miridae : {
                  Kanakamiris : {},
                  Neophloeobia : {
                      incisa : {}
                  }
               }
           },
           Lepidoptera : {
               Nymphalidae : {
                  Ephinephile : {
                      rawnsleyi : {}
                  }
               }
           }
        }

    …perché lavorare con gli oggetti, piuttosto che le matrici rende più facile per verificare se il bambino elementi già esistenti. Dopo aver creato la struttura di cui sopra ho poi il processo per l’ultima volta per ottenere il vostro finale di output desiderato. Quindi:

    //start by remapping the data to an array of arrays
    var organisms = data.organisms.map(function(v) {
            return v.name.split(".");
        });
    
    //this function recursively processes the above array of arrays
    //to create an object whose properties are also objects
    function addToHeirarchy(val, level, heirarchy) {
        if (val[level]) {
            if (!heirarchy.hasOwnProperty(val[level]))
                heirarchy[val[level]] = {};
            addToHeirarchy(val, level + 1, heirarchy[val[level]]);
        }
    }
    var working = {};    
    for (var i = 0; i < organisms.length; i++)
        addToHeirarchy(organisms[i], 0, working);
    
    //this function recursively processes the object created above
    //to create the desired final structure
    function remapHeirarchy(item) {
        var children = [];
        for (var k in item) {
            children.push({
                "name" : k,
                "children" : remapHeirarchy(item[k])
            });
        }
        return children;
    }
    
    var heirarchy = {
        "name" : "ROOT",
        "children" : remapHeirarchy(working)
    };

    Demo: http://jsfiddle.net/a669F/1/

    • Mi piace il modo in cui hai utilizzato hasOwnProperty. iniziale di sperimentazione di questo trasforma davvero originale dati in un formato desiderato. Penso che sia la funzione ricorsiva schema che ho bisogno di studiare e imparare di più. +1 per questa risposta
  3. 2

    Una risposta alternativa alla mia domanda….Nel giorno passato ho imparato a non molto di più sulle d3.js e in relazione a questa domanda d3.nido() con .tasto() e .voci() è il mio amico (tutti d3 funzioni).
    Questa risposta implica la modifica di dati iniziali, in modo che non può qualificarsi come una buona risposta alla specifica domanda che ho chiesto. Tuttavia, se qualcuno ha una domanda simile e può cambiare le cose sul server quindi questa è una soluzione abbastanza semplice:

    restituire i dati dal database in questo formato:

    json = {'Organisms': [
        { 'Rank_Order': 'Hemiptera',
          'Rank_Family': 'Miridae',
          'Rank_Genus': 'Kanakamiris',
          'Rank_Species': '' },
        {}, ...
    ]}

    Quindi utilizzando d3.nido()

    organismNest = d3.nest()
        .key(function(d){return d.Rank_Order;})
        .key(function(d){return d.Rank_Family;})
        .key(function(d){return d.Rank_Genus;})
        .key(function(d){return d.Rank_Species;})
        .entries(json.Organism);

    restituisce:

    {
    key: "Hemiptera"
      values: [
        {
          key: "Cicadidae"
          values: [
            {
              key: "Pauropsalta "
              values: [
                {
                  key: "siccanus"
                  values: [
                           Rank_Family: "Cicadidae"
                           Rank_Genus: "Pauropsalta "
                           Rank_Order: "Hemiptera"
                           Rank_Species: "siccanus"
                           AnotherOriginalDataKey: "original data value"
    
    etc etc, nested and lovely

    Restituisce qualcosa di molto simile a una matrice che ho descritto come il mio formato desiderato sopra in questione, con alcune differenze. In particolare, non C’è tutti che racchiude l’elemento PRINCIPALE e anche considerando che le chiavi volevo inizialmente erano “nome” e “bambini” .nido() restituisce le chiavi come “chiave” e i “valori”, rispettivamente.
    Queste alternative tasti sono abbastanza facile da usare in d3.js solo la definizione di opportuni dati le funzioni get (di base d3 concetto) … ma che è sempre al di là dello scopo originale della domanda … spero che qualcuno aiuta troppo

Lascia un commento