繁体   English   中英

递归查找对象上的键

[英]Recursively find keys on an object

我有一个这样的javascript对象;

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

给定一系列键['brand','group','newGroup','newSubGroup'],我想将这些键分为找到的和丢失的键。 因此,对于上面的结构,我应该回来;

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

我正在使用ES6并具有可用的lodash,但正在努力寻找一种干净的方法来实现这一点。

这不仅是检查存在性,而是递归地找到键并返回存在的键和剩余的键。

这是一种相当粗略的方法。

 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: [] }); } 

您可以使用为您量身定制的此功能;)

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)
  }
})

  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

我编写了一个函数以从嵌套对象中递归地获取唯一键,然后过滤了您提到的所有键的数组,这些键检查了函数结果中是否存在。

 var thisObject = { brand: { group: { subGroup: { items: [] }, otherSub: { items: [] } } } }; var arr_full = ['brand', 'group', 'newGroup', 'newSubGroup'] ; var key_array = []; function addToKeyArray( key_array, object ){ for( var key in object ){ // only get unique keys if( key_array.indexOf( key ) === -1 ){ key_array.push( key ); } // concat the result of calling this function recurrsively on object[key] key_array.concat( addToKeyArray( key_array, object[key] ) ); } 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 ) 

您可以在另一个函数内使用for...in循环创建递归函数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)) 

为了保持内容整洁易读,您可以在嵌套函数内使用“ 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))); 

即使这个问题有点老了,我还是想提出一个解决这个问题的简短方法。

const recursivelyGetKeys = obj => Object.keys(obj).map(key => typeof obj[key] === 'object' 
? [...recursivelyGetKeys(obj[key]), key] : [key]).reduce((p, c) => [...p, ...c], [])

此函数将返回对象中的所有键,因此使用以下命令调用数组arr

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

将输出:

const keys = recursivelyGetKeys(arr) // = ["items", "subGroup", "items", "otherSub", "group", "brand"]

现在,找到它的交集并find = ['brand', 'group', 'newGroup', 'newSubGroup'] ,执行以下操作:

const found = keys.filter(key => find.some(val === key))
const missing = keys.filter(key => find.every(val !== key))

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM