Find by key deep in a nested array

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

Let\'s say I have an object:

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


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

    I'd like to suggest an amendment to Zach/RegularMike's answer (but don't have the "reputation" to be able to comment!). I found there solution a very useful basis, but suffered in my application because if there are strings within arrays it would recursively call the function for every character in the string (which caused IE11 & Edge browsers to fail with "out of stack space" errors). My simple optimization was to add the same test used in the "object" clause recursive call to the one in the "array" clause:

    if (arrayElem instanceof Object || arrayElem instanceof Array) {
    

    Thus my full code (which is now looking for all instances of a particular key, so slightly different to the original requirement) is:

    // Get all instances of specified property deep within supplied object
    function getPropsInObject(theObject, targetProp) {
        var result = [];
        if (theObject instanceof Array) {
            for (var i = 0; i < theObject.length; i++) {
                var arrayElem = theObject[i];
                if (arrayElem instanceof Object || arrayElem instanceof Array) {
                    result = result.concat(getPropsInObject(arrayElem, targetProp));
                }
            }
        } else {
            for (var prop in theObject) {
                var objProp = theObject[prop];
                if (prop == targetProp) {
                    return theObject[prop];
                }
                if (objProp instanceof Object || objProp instanceof Array) {
                    result = result.concat(getPropsInObject(objProp, targetProp));
                }
            }
        }
        return result;
    }
    
    0 讨论(0)
  • 2020-11-22 15:57

    I would try not to reinvent the wheel. We use object-scan for all our data processing needs. It's conceptually very simple, but allows for a lot of cool stuff. Here is how you would solve your specific question

    const objectScan = require('object-scan');
    
    const find = (id, input) => objectScan(['**'], {
      abort: true,
      rtn: 'value',
      filterFn: ({ value }) => value.id === id
    })(input);
    
    const data = [{
      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(find('1', data));
    // => { image: 'http://www.asdasd.com', title: 'Sandals', id: '1', content: {} }
    
    0 讨论(0)
  • 2020-11-22 15:58

    I found this page through googling for the similar functionalities. Based on the work provided by Zach and regularmike, I created another version which suits my needs.
    BTW, teriffic work Zah and regularmike! I'll post the code here:

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

    What it does is it find any object inside of obj with property name and value matching to targetProp and targetValue and will push it to the finalResults array. And Here's the jsfiddle to play around: https://jsfiddle.net/alexQch/5u6q2ybc/

    0 讨论(0)
  • 2020-11-22 16:00

    Recursion is your friend. I updated the function to account for property arrays:

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

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

    0 讨论(0)
  • 2020-11-22 16:00

    Improved answer to take into account circular references within objects. It also displays the path it took to get there.

    In this example, I am searching for an iframe that I know is somewhere within a global object:

    const objDone = []
    var i = 2
    function getObject(theObject, k) {
        if (i < 1 || objDone.indexOf(theObject) > -1) return
        objDone.push(theObject)
        var result = null;
        if(theObject instanceof Array) {
            for(var i = 0; i < theObject.length; i++) {
                result = getObject(theObject[i], i);
                if (result) {
                    break;
                }   
            }
        }
        else
        {
            for(var prop in theObject) {
                if(prop == 'iframe' && theObject[prop]) {
                    i--;
                    console.log('iframe', theObject[prop])
                    return theObject[prop]
                }
                if(theObject[prop] instanceof Object || theObject[prop] instanceof Array) {
                    result = getObject(theObject[prop], prop);
                    if (result) {
                        break;
                    }
                } 
            }
        }
        if (result) console.info(k)
        return result;
    }
    

    Running the following: getObject(reader, 'reader') gave the following output and the iframe element in the end:

    iframe // (The Dom Element)
    _views
    views
    manager
    rendition
    book
    reader
    

    NOTE: The path is in reverse order reader.book.rendition.manager.views._views.iframe

    0 讨论(0)
  • 2020-11-22 16:00

    This piece of code allows you to get all objects within a JSON whose key is user-defined.

    function main(obj = {}, property){
     const views = [];
    
     function traverse(o) {
        for (var i in o) {
          if(i === property) views.push(o[i]);
          if (!!o[i] && typeof(o[i])=="object") {
            console.log(i, o[i]);
            traverse(o[i]);
          } else {
            console.log(i, o[i]);
          }
        }
        }
    
      traverse(obj);
      return views;
    
    }
    
    
    
    

    Here is an example:

    const obj = {
        id: 'id at level 1',
        level2: {
          id: 'id at level 2',
          level3: {
            id: 'id at level 3',
            level4: {
              level5: {
                id: 'id at level 5'
              }
           }
        }
      },
      text: ''
    }
    
    main(obj, 'id');
    
    
    0 讨论(0)
提交回复
热议问题