-1

I receive multiple JSONs from an API (17 API calls with Promise.all() ). For example

[
  {
    key: value,
    key: value,
    key: value,
    key: value,
    values: [
      {
        key: value,
        key: value,
        key: value,
        keyIWant: value
      }
      {
        key: value,
        key: value,
        key: value,
        keyIWant: value
      }
      {
        key: value,
        key: value,
        key: value,
        keyIWant: value
      }
    ]
  }
  {
    key: value,
    key: value,
    key: value,
    key: value,
    values: [
      {
        key: value,
        key: value,
        key: value,
        keyIWant: value
      }
      {
        key: value,
        key: value,
        key: value,
        keyIWant: value
      }
      {
        key: value,
        key: value,
        key: value,
        keyIWant: value
      }
    ]
  }
  {
    key: value,
    key: value,
    key: value,
    key: value,
    values: [
      {
        key: value,
        key: value,
        key: value,
        keyIWant: value
      }
      {
        key: value,
        key: value,
        key: value,
        keyIWant: value
      }
      {
        key: value,
        key: value,
        key: value,
        keyIWant: value
      }
    ]
  }
]

and I really have no idea to get the key I want (and to get it on a more generic approach). So far my attempts have been

static _findKey(nestedData) { 
    const result = [];
    const buffer = [];
    for (const prop in nestedData) {
        const value = nestedData[prop];
        if (typeof value === "object") {
            buffer.push(Class._findKey(value)); 
        }
        if (prop === "keyIWant") { // key would be an argument from the function if it'd worked 
             result.push(value);   // doesn't work because of recursive call?
        }
    }
    return result;
}

and

static _findKey(projects) { // 
    return projects.forEach(project => {
        return project.values.forEach(projectValue => {
            return projectValue.key;
        });
    });
}

Do you have some more ideas? I'm still learning JavaScript and thus want a clean and comprehensive solution, but couldn't build one by myself.

Tobias
  • 71
  • 2
  • 7
  • if you know the path why not use lodash to filter and get what you need? [Example here on this post](https://stackoverflow.com/questions/17096988/lodash-how-do-i-use-filter-when-i-have-nested-object) – Dennington-bear Jul 19 '17 at 13:14
  • 1
    look into https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map – jumpdart Jul 19 '17 at 13:16
  • I know the path for this specific example, but there may be other examples I don't the path. My goal was to build one generic function to reuse it the whole time, just by giving the key as argument and get all corresponding values – Tobias Jul 19 '17 at 13:18

2 Answers2

3

You can use below function to get all values stored at the key you specify:

function getKeyValues(arr, key) {
    return arr.reduce((a,b) => {
        let keys = Object.keys(b);
        keys.forEach(v => {
            if (Array.isArray(b[v])) a = a.concat(getKeyValues(b[v], key));
            if (v === key) a = a.concat(b[v]);
        });
        return a;
    }, [])
}

Call with

getKeyValues(arr, "keyIWant")

let arr = [{
    key: 'foo',
    values: [{
        key: 'value',
        keyIWant: 'keyIWant1'
      },
      {
        key: 'value',
        keyIWant: 'keyIWant2'
      }, {
        key: 'value',
        keyIWant: 'keyIWant3'
      }
    ]
  },
  {
    key: 'foo',
    values: [{
        key: 'value',
        keyIWant: 'keyIWant4'
      },
      {
        key: 'value',
        keyIWant: 'keyIWant5'
      }, {
        key: 'value',
        keyIWant: 'keyIWant6'
      }
    ]
  }
];

function getKeyValues(arr, key) {
  return arr.reduce((a, b) => {
    let keys = Object.keys(b);
    keys.forEach(v => {
      if (Array.isArray(b[v])) a = a.concat(getKeyValues(b[v], key));
      if (v === key) a = a.concat(b[v]);
    });
    return a;
  }, []);
}


console.log(getKeyValues(arr, "keyIWant"));
baao
  • 71,625
  • 17
  • 143
  • 203
0

We use object-scan for many data processing tasks like yours. It's powerful once you wrap your head around it. Here is how you could answer your question

// const objectScan = require('object-scan');

const find = (input) => objectScan(['**.keyIWant'], { rtn: 'value' })(input);

const arr = [{ key: 'foo', values: [{ key: 'value', keyIWant: 'keyIWant1' }, { key: 'value', keyIWant: 'keyIWant2' }, { key: 'value', keyIWant: 'keyIWant3' }] }, { key: 'foo', values: [{ key: 'value', keyIWant: 'keyIWant4' }, { key: 'value', keyIWant: 'keyIWant5' }, { key: 'value', keyIWant: 'keyIWant6' }] }];

console.log(find(arr));
/* =>
[ 'keyIWant6',
  'keyIWant5',
  'keyIWant4',
  'keyIWant3',
  'keyIWant2',
  'keyIWant1' ]
*/
.as-console-wrapper {max-height: 100% !important; top: 0}
<script src="https://bundle.run/object-scan@13.8.0"></script>

Disclaimer: I'm the author of object-scan

vincent
  • 1,953
  • 3
  • 18
  • 24