递归地查找对象上的键

时间:2017-07-19 17:31:16

标签: javascript

我有一个像这样的javascript对象;

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

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

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

我正在使用ES6并且可以使用lodash,但很难找到一种干净的方式来制作它。

这不仅仅是检查存在,它是递归地找到键并返回那些存在的和剩下的。

7 个答案:

答案 0 :(得分: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: [] });
}




答案 1 :(得分: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 :(得分: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

的导线方法

答案 3 :(得分:0)

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

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 )

答案 4 :(得分:0)

您可以使用另一个函数内的for...in循环创建递归函数,并返回对象作为结果。

&#13;
&#13;
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))
&#13;
&#13;
&#13;

答案 5 :(得分: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)));

答案 6 :(得分:0)

尽管这个问题有点老了,但我想提出一个相当简短的解决方案。

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