2017-07-19 39 views
0

我有一個像這樣構造的JavaScript對象;遞歸查找對象上的鍵

brand: { 
    group: { 
    subGroup: { 
     items: [] 
    }, 
    otherSub: { 
     items: [] 
    } 
    } 
} 

鑑於鍵陣列[「品牌」,「基團」,「新聞組」,「newSubGroup」]我要拆分的鍵成發現丟失的鑰匙。所以對於上面的結構,我應該回來;

present = ['brand', 'group'] 
missing = ['newGroup', 'newSubGroup'] 

我正在使用ES6,並有lodash可用,但努力找到一個乾淨的方式來產生這個。

這不僅僅是檢查存在,它是遞歸地找到鍵並返回那些存在的和剩餘的。

+0

不是一個重複。我試圖找到最簡潔的方式遞歸地通過對象工作,並將數組分爲找到的鍵和不存在的鍵。 – james2m

+0

也許矯枉過正,但你見過[this object diffing package](https://www.npmjs.com/package/deep-diff)嗎?我之前使用過它,我發現它很有用。 – alexanderbird

+0

另外,如果你正在努力尋找一個乾淨的方式來做到這一點,你可以包括你已經能夠做到的「不乾淨」的方式嗎? – alexanderbird

回答

1

你可以使用你做這個功能;)

var getAttrs = function(obj) { 
    return [].concat.apply([], Object.keys(obj).map(function (key) { 
    var results = [key] 
    if (typeof obj[key] === 'object') { 
     Array.prototype.push.apply(results, getAttrs(obj[key])) 
    } 
    return results 
    })) 
} 

它返回性能和兒童的屬性列表。

getAttrs({brand: { 
    group: { 
    subGroup: { 
     items: [] 
    }, 
    otherSub: { 
     items: [] 
    } 
    } 
}}) 

> ["brand", "group", "subGroup", "items", "otherSub", "items"] 

而且你可以使用它像這樣:

var lookingFor = ['brand', 'group', 'newGroup', 'newSubGroup'] 
var existings = getAttrs(obj) 

var missings = [] 
var presents = [] 

lookingFor.forEach(attr => { 
    if (existings.indexOf(attr) === -1) { 
    missings.push(attr) 
    } else { 
    presents.push(attr) 
    } 
}) 
2

這裏是一個可行的相當粗略的方式。

const find = (keys, obj) => { 
 
    const string = JSON.stringify(obj); 
 
    return keys.reduce(({ present, missing }, key) => { 
 
    const match = string.match(new RegExp(`"${key}":`)); 
 
    if (match) { 
 
     present.push(key); 
 
    } else { 
 
     missing.push(key); 
 
    } 
 
    return { present, missing }; 
 
    }, { present: [], missing: [] }); 
 
}

+0

我非常喜歡這個簡潔,但是JSON.stringify有點讓我感到不安。我想這就是你粗略的意思。 – james2m

0

var toFind = ['brand', 'group', 'newGroup', 'newSubGroup'], 
 
     found = []; 
 

 
    var o = { 
 
     brand: { 
 
      group: { 
 
       subGroup: { 
 
        items: [] 
 
       }, 
 
       otherSub: { 
 
        items: [] 
 
       } 
 
      } 
 
     } 
 
    } 
 

 
    //called with every property and its value 
 
    function process(key,value) { 
 
     var i = toFind.indexOf(key); 
 
     if(i !== -1){ 
 
      found.push(key); 
 
      toFind.splice(i, 1); 
 
     } 
 
    } 
 
    
 
    function traverse(o,func) { 
 
     if(!toFind.length) return; 
 
     for (var i in o) { 
 
      func.apply(this,[i,o[i]]); 
 
      if (o[i] !== null && typeof(o[i])=="object") { 
 
       //going one step down in the object tree!! 
 
       traverse(o[i],func); 
 
      } 
 
     } 
 
    } 
 
    
 
    traverse(o,process); 
 

 
    console.log(found); // present 
 
    console.log(toFind); // absent

https://stackoverflow.com/a/722732/1335165

0

我寫了一個函數來從嵌套對象遞歸獲得唯一密鑰截取遍歷方法中,然後過濾的陣列你提到的所有鍵都檢查哪些是pres在我的功能的結果。

var thisObject = { 
 
\t brand: { 
 
    \t \t group: { 
 
    \t \t subGroup: { 
 
     \t \t \t items: [] 
 
    \t \t }, 
 
    \t \t otherSub: { 
 
     \t \t \t items: [] 
 
    \t \t } 
 
     } 
 
    \t } 
 
}; 
 

 
var arr_full = ['brand', 'group', 'newGroup', 'newSubGroup'] ; 
 

 
var key_array = []; 
 

 
function addToKeyArray(key_array, object){ 
 
\t 
 
    for(var key in object){ 
 
    
 
    \t // only get unique keys 
 
    \t if(key_array.indexOf(key) === -1){ 
 
     \t key_array.push(key); 
 
     } 
 
    
 
    \t // concat the result of calling this function recurrsively on object[key] 
 
    \t key_array.concat(addToKeyArray(key_array, object[key])); \t 
 
    } 
 
    
 
    return key_array; 
 
} 
 

 

 
var test = addToKeyArray([], thisObject); 
 

 
var missing = arr_full.filter(function(el) { 
 
    return test.indexOf(el) < 0; 
 
}); 
 

 
console.log(test); 
 
console.log(missing)

0

您可以使用另一個函數內部for...in循環創建遞歸函數,返回對象作爲結果..

var obj = {"brand":{"group":{"subGroup":{"items":[]},"otherSub":{"items":[]}}}} 
 
var keys = ['brand', 'group', 'newGroup', 'newSubGroup'] ; 
 

 
function findKeys(data, keys) { 
 
    keys = keys.slice(); 
 
    
 
    function findPresent(data, keys) { 
 
    var result = [] 
 
    
 
    for(var i in data) { 
 
     if(typeof data[i] == 'object') result.push(...findPresent(data[i], keys)) 
 
     var index = keys.indexOf(i); 
 
     if(index != -1) result.push(...keys.splice(index, 1)) 
 
    } 
 
    
 
    return result 
 
    } 
 
    
 
    return {present: findPresent(data, keys), missing: keys} 
 
} 
 

 
console.log(findKeys(obj, keys))

0

爲了保持乾淨和可讀性你可以在嵌套樂趣中使用「for in」用於遞歸。

function recur(obj) { 
 
    let preMiss = { 
 
    present: [], 
 
    missing: [] 
 
    } 
 
    let root = traverse => { 
 
    for (let key in traverse) { 
 
     if (Array.isArray(traverse[key].items)) { 
 
     preMiss.missing.push(key); 
 
     } 
 
     if (typeof traverse[key] === 'object' && !Array.isArray(traverse[key].items)) { 
 
     preMiss.present.push(key); 
 
     root(traverse[key]) 
 
     } 
 
    } 
 
    } 
 
    root(obj); 
 
    return preMiss; 
 
} 
 

 
const object = { 
 
    brand: { 
 
    group: { 
 
     subGroup: { 
 
     items: [] 
 
     }, 
 
     otherSub: { 
 
     items: [] 
 
     } 
 
    } 
 
    } 
 
} 
 

 

 
console.log(Object.entries(recur(object)));