Find by key deep in a nested array

后端 未结 17 1309
礼貌的吻别
礼貌的吻别 2020-11-22 15:41

Let\'s say I have an object:

[
    {
        \'title\': \"some title\"
        \'channel_id\':\'123we\'
        \'options\': [
                    {
                 


        
相关标签:
17条回答
  • 2020-11-22 15:43

    If you want to get the first element whose id is 1 while object is being searched, you can use this function:

    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"){
                var o = customFilter(object[Object.keys(object)[i]]);
                if(o != null)
                    return o;
            }
        }
    
        return null;
    }
    

    If you want to get all elements whose id is 1, then (all elements whose id is 1 are stored in result as you see):

    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);
            }
        }
    }
    
    0 讨论(0)
  • 2020-11-22 15:44

    Another recursive solution, that works for arrays/lists and objects, or a mixture of both:

    function deepSearchByKey(object, originalKey, matches = []) {
    
        if(object != null) {
            if(Array.isArray(object)) {
                for(let arrayItem of object) {
                    deepSearchByKey(arrayItem, originalKey, matches);
                }
            } else if(typeof object == 'object') {
    
                for(let key of Object.keys(object)) {
                    if(key == originalKey) {
                        matches.push(object);
                    } else {
                        deepSearchByKey(object[key], originalKey, matches);
                    }
    
                }
    
            }
        }
    
    
        return matches;
    }
    

    usage:

    let result = deepSearchByKey(arrayOrObject, 'key'); // returns an array with the objects containing the key
    
    0 讨论(0)
  • 2020-11-22 15:45

    Improved @haitaka answer, using the key and predicate

    function  deepSearch (object, key, predicate) {
        if (object.hasOwnProperty(key) && predicate(key, object[key]) === true) return object
    
        for (let i = 0; i < Object.keys(object).length; i++) {
          let value = object[Object.keys(object)[i]];
          if (typeof value === "object" && value != null) {
            let o = deepSearch(object[Object.keys(object)[i]], key, predicate)
            if (o != null) return o
          }
        }
        return null
    }
    

    So this can be invoked as:

    var result = deepSearch(myObject, 'id', (k, v) => v === 1);
    

    or

    var result = deepSearch(myObject, 'title', (k, v) => v === 'Some Recommends');
    

    Here is the demo: http://jsfiddle.net/a21dx6c0/

    EDITED

    In the same way you can find more than one object

    function deepSearchItems(object, key, predicate) {
            let ret = [];
            if (object.hasOwnProperty(key) && predicate(key, object[key]) === true) {
                ret = [...ret, object];
            }
            if (Object.keys(object).length) {
                for (let i = 0; i < Object.keys(object).length; i++) {
                    let value = object[Object.keys(object)[i]];
                    if (typeof value === "object" && value != null) {
                        let o = this.deepSearchItems(object[Object.keys(object)[i]], key, predicate);
                        if (o != null && o instanceof Array) {
                            ret = [...ret, ...o];
                        }
                    }
                }
            }
            return ret;
        }
    
    0 讨论(0)
  • 2020-11-22 15:47

    Another (somewhat silly) option is to exploit the naturally recursive nature of JSON.stringify, and pass it a replacer function which runs on each nested object during the stringification process:

    const input = [{
      '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': {}
          }]
        }]
      }]
    }];
    
    console.log(findNestedObj(input, 'id', '1'));
    
    function findNestedObj(entireObj, keyToFind, valToFind) {
      let foundObj;
      JSON.stringify(input, (_, nestedValue) => {
        if (nestedValue && nestedValue[keyToFind] === valToFind) {
          foundObj = nestedValue;
        }
        return nestedValue;
      });
      return foundObj;
    };

    0 讨论(0)
  • 2020-11-22 15:53

    @Iulian Pinzaru's answer was almost exactly what I needed, but it doesn't work if your objects have any null values. This version fixes that.

    function  deepSearch (object, key, predicate) {
      if (object.hasOwnProperty(key) && predicate(key, object[key]) === true) return object
    
      for (let i = 0; i < Object.keys(object).length; i++) {
        const nextObject = object[Object.keys(object)[i]];
        if (nextObject && typeof nextObject === "object") {
          let o = deepSearch(nextObject, key, predicate)
          if (o != null) return o
        }
      }
      return null
    }
    
    0 讨论(0)
  • 2020-11-22 15:54

    What worked for me was this lazy approach, not algorithmically lazy ;)

    if( JSON.stringify(object_name).indexOf("key_name") > -1 ) {
        console.log("Key Found");
    }
    else{
        console.log("Key not Found");
    }
    
    0 讨论(0)
提交回复
热议问题