2013-03-20 11 views
33

Diciamo che ho un oggetto:Trova con chiave profonda in un oggetto nidificato

[ 
    { 
     'title': "some title" 
     'channel_id':'123we' 
     'options': [ 
        { 
       'channel_id':'abc' 
       'image':'http://asdasd.com/all-inclusive-block-img.jpg' 
       'title':'All-Inclusive' 
       'options':[ 
        { 
         'channel_id':'dsa2' 
         'title':'Some Recommends' 
         'options':[ 
          { 
           'image':'http://www.asdasd.com'         'title':'Sandals' 
           'id':'1' 
           'content':{ 
            ... 

Voglio trovare l'unico oggetto in cui l'ID è 1. C'è una funzione per qualcosa di simile? Potrei usare il metodo di Underscore _.filter, ma dovrei iniziare in alto e filtrare verso il basso.

risposta

48

La ricorsione è un tuo amico. Ho aggiornato la funzione per tenere conto di array di proprietà:

function getObject(theObject) { 
    var result = null; 
    if(theObject instanceof Array) { 
     for(var i = 0; i < theObject.length; i++) { 
      result = getObject(theObject[i]); 
      if (result) { 
       break; 
      } 
     } 
    } 
    else 
    { 
     for(var prop in theObject) { 
      console.log(prop + ': ' + theObject[prop]); 
      if(prop == 'id') { 
       if(theObject[prop] == 1) { 
        return theObject; 
       } 
      } 
      if(theObject[prop] instanceof Object || theObject[prop] instanceof Array) { 
       result = getObject(theObject[prop]); 
       if (result) { 
        break; 
       } 
      } 
     } 
    } 
    return result; 
} 

aggiornato jsFiddle: http://jsfiddle.net/FM3qu/7/

+1

Ma aspetta, guarda il mio codice, le opzioni potrebbero avere molti oggetti [{}, {}]. come funzionerebbe? – Harry

+0

Lì. Ho menzionato prima che doveva essere aggiornato per tenere conto degli array, così ci sei. – Zach

+0

Ok, vedo, grazie, non provarlo ora – Harry

6

Se si desidera ottenere il primo elemento il cui ID è 1, mentre oggetto viene cercata, è possibile utilizzare questa funzione:

function customFilter(object){ 
    if(object.hasOwnProperty('id') && object["id"]==1) 
     return object; 

    for(var i=0;i<Object.keys(object).length;i++){ 
     if(typeof object[Object.keys(object)[i]]=="object"){ 
      o=customFilter(object[Object.keys(object)[i]]); 
      if(o!=null) 
       return o; 
     } 
    } 

    return null; 
} 

Se si desidera ottenere tutti gli elementi il ​​cui ID è 1, allora (tutti elementi il ​​cui ID è 1 sono memorizzati nel risultato, come si vede):

function customFilter(object,result){ 
    if(object.hasOwnProperty('id') && object.id=1) 
     result.push(object); 

    for(var i=0;i<Object.keys(object).length;i++){ 
     if(typeof object[Object.keys(object)[i]]=="object"){ 
      customFilter(object[Object.keys(object)[i]],result); 
     } 
    } 
} 
-8

Se si sta già utilizzando sottolineatura, utilizzare _.find()

_.find(yourList, function (item) { 
    return item.id === 1; 
}); 
+0

Sarebbe funziona Se non ci fosse voce nel primo livello dell'oggetto, ma la sua non è, il suo nidificato in – Harry

+1

Dang. Stavo guardando il mio telefono e il modo in cui l'oggetto lo avvolgeva faceva sembrare che fosse al primo livello. Ho pensato che sembrasse troppo facile. – rhodesjason

+1

sì, vorrei che fosse così semplice :-) – Harry

1

Ho creato libreria per questo scopo: https://github.com/dominik791/obj-traverse

È possibile utilizzare findFirst() metodo come questo:

var foundObject = findFirst(rootObject, 'options', { 'id': '1' }); 

E ora la variabile foundObject memorizza un riferimento all'oggetto che si è l per.

2

Ho trovato questa pagina tramite google per le funzionalità simili. Sulla base del lavoro fornito da Zach e regularmike, ho creato un'altra versione che si adatta alle mie esigenze.
BTW, lavoro teriffic Zah e regularmike! Vi posto il codice qui:

function findObjects(obj, targetProp, targetValue, finalResults) { 

    function getObject(theObject) { 
    let result = null; 
    if (theObject instanceof Array) { 
     for (let i = 0; i < theObject.length; i++) { 
     getObject(theObject[i]); 
     } 
    } 
    else { 
     for (let prop in theObject) { 
     if(theObject.hasOwnProperty(prop)){ 
      console.log(prop + ': ' + theObject[prop]); 
      if (prop === targetProp) { 
      console.log('--found id'); 
      if (theObject[prop] === targetValue) { 
       console.log('----found porop', prop, ', ', theObject[prop]); 
       finalResults.push(theObject); 
      } 
      } 
      if (theObject[prop] instanceof Object || theObject[prop] instanceof Array){ 
      getObject(theObject[prop]); 
      } 
     } 
     } 
    } 
    } 

    getObject(obj); 

} 

Ciò che fa è che trovare qualsiasi oggetto all'interno di obj con nome della proprietà e di corrispondenza valore targetProp e targetValue e la spingerà alla matrice finalResults. Ed ecco la jsfiddle di giocare: https://jsfiddle.net/alexQch/5u6q2ybc/

+0

questo potrebbe essere ulteriormente migliorato con 'return'ing la matrice' finalResults' invece di accettare un'altra variabile come input per scrivere a – RozzA

Problemi correlati