简体   繁体   中英

How to return a array from array of object based on multiple keys

I have an array of object having with multiple value but I have to filter values based on keys into an array and also merge value to array having same value. I have tried in different steps can it be done in single map/filter/reduce?

const a = [
    {abc: ['add', 'edit'], cond: []},
    {cond: ['add_cond', 'edit_cond', 'view_cond'], matx: ['add_matx', 'edit_matx', 'delete_matx'], work: ['add_work', 'edit_work'], def: []},
    {cond: ['add_cond', 'edit_cond', 'view_cond', 'delete_cond'], matx: ['add_matx', 'edit_matx', 'view_matx', 'store_matx'], work: ['view_work', 'delete_work']},
];
const expected result = {
    cond: ['add_cond', 'edit_cond', 'view_cond', 'delete_cond'],  matx: ['add_matx', 'edit_matx', 'view_matx', 'store_matx', 'delete_matx'], work: ['add_work', 'edit_work','view_work', 'delete_work']
}

const b = a.map(el => el.cond);

const c = a.map(el => el.matx);

const d = a.map(el => el.work);

result = {cond: [...b], matx: [...c], work: [...d]}

You could collect all wanted properties' values into a set and build a new object from the key/value pairs.

 const data = [{ abc: ['add', 'edit'], cond: [] }, { cond: ['add_cond', 'edit_cond', 'view_cond'], matx: ['add_matx', 'edit_matx', 'delete_matx'], work: ['add_work', 'edit_work'], def: [] }, { cond: ['add_cond', 'edit_cond', 'view_cond', 'delete_cond'], matx: ['add_matx', 'edit_matx', 'view_matx', 'store_matx'], work: ['view_work', 'delete_work'] }], keys = ['cond', 'matx', 'work'], addToSet = (s, v) => s.add(v), result = Object.fromEntries(keys.map(k => [ k, [...data.reduce((r, o) => (o[k] || []).reduce(addToSet, r), new Set)] ])); console.log(result);
 .as-console-wrapper { max-height: 100%;important: top; 0; }

It cant be done with forEach... .map() .reduce() and .filter() will always return an array not an object.

 const a = [ {abc: ['add', 'edit'], cond: []}, {cond: ['add_cond', 'edit_cond', 'view_cond'], matx: ['add_matx', 'edit_matx', 'delete_matx'], work: ['add_work', 'edit_work'], def: []}, {cond: ['add_cond', 'edit_cond', 'view_cond', 'delete_cond'], matx: ['add_matx', 'edit_matx', 'view_matx', 'store_matx'], work: ['view_work', 'delete_work']}, ]; const result = {cond: [], work: [], matx: []} a.forEach(x=> { x.cond && result.cond.push(...x.cond); x.work && result.work.push(...x.work); x.matx && result.work.push(...x.matx); } ); console.log(result);

const a = [
  { abc: ["add", "edit"], cond: [] },
  {
    cond: ["add_cond", "edit_cond", "view_cond"],
    matx: ["add_matx", "edit_matx", "delete_matx"],
    work: ["add_work", "edit_work"],
    def: [],
  },
  {
    cond: ["add_cond", "edit_cond", "view_cond", "delete_cond"],
    matx: ["add_matx", "edit_matx", "view_matx", "store_matx"],
    work: ["view_work", "delete_work"],
  },
];

function mapper(a) {
  let result = {};
  for (let i = 0; i < a.length - 1; i++) {
    result = Object.assign(a[i], a[i + 1]);
  }
  return result;
}

console.log(mapper(a));

RESULT--->

{
  cond: [ 'add_cond', 'edit_cond', 'view_cond', 'delete_cond' ],
  matx: [ 'add_matx', 'edit_matx', 'view_matx', 'store_matx' ],
  work: [ 'view_work', 'delete_work' ],
  def: []
}

You can achieve this using a single reduce method. All keys are evaluated dynamically, so no matter how many keys you add/remove to your objects you get dynamically added keys:

 const a = [ {abc: ['add', 'edit'], cond: []}, {cond: ['add_cond', 'edit_cond', 'view_cond'], matx: ['add_matx', 'edit_matx', 'delete_matx'], work: ['add_work', 'edit_work'], def: []}, {cond: ['add_cond', 'edit_cond', 'view_cond', 'delete_cond'], matx: ['add_matx', 'edit_matx', 'view_matx', 'store_matx'], work: ['view_work', 'delete_work']}, ]; const result = a.reduce((prev, cur) => { const keys = Object.keys(cur); keys.forEach(el => { if(prev[el] === undefined) prev[el] = [] prev[el].push(cur[el]) prev[el] = prev[el].flat() }) return prev }, {}) console.log(result)

So based on that you only want arrays you only miss .forEach to iterate and most forEach-anwers here are wrong, you can go through every loop and break down the problem:

 const a = [ {abc: ['add', 'edit'], cond: []}, {cond: ['add_cond', 'edit_cond', 'view_cond'], matx: ['add_matx', 'edit_matx', 'delete_matx'], work: ['add_work', 'edit_work'], def: []}, {cond: ['add_cond', 'edit_cond', 'view_cond', 'delete_cond'], matx: ['add_matx', 'edit_matx', 'view_matx', 'store_matx'], work: ['view_work', 'delete_work']}, ]; const result = {cond: [], matx: [], work: []} a.forEach( current_dict => { Object.entries(current_dict).filter(current_entry => current_entry[0] in result).forEach( current_entry => { current_entry[1].filter(value =>.result[current_entry[0]].includes(value)).forEach( value => { result[current_entry[0]].push(value) } ) } ) } ) console.log(result)

Note that the arrays are not ordered. You should use dictionaries instead arrays or a type of mapping function like condOrderFunction(option){/*something*/return index} if you need an order.

I'm not sure why its not the same as the expected result but try this:

 const a = [ {abc: ['add', 'edit'], cond: []}, {cond: ['add_cond', 'edit_cond', 'view_cond'], matx: ['add_matx', 'edit_matx', 'delete_matx'], work: ['add_work', 'edit_work'], def: []}, {cond: ['add_cond', 'edit_cond', 'view_cond', 'delete_cond'], matx: ['add_matx', 'edit_matx', 'view_matx', 'store_matx'], work: ['view_work', 'delete_work']}, ]; const expectedResult = { cond: ['add_cond', 'edit_cond', 'view_cond', 'delete_cond'], matx: ['add_matx', 'edit_matx', 'view_matx', 'store_matx', 'delete_matx'], work: ['add_work', 'edit_work','view_work', 'delete_work'] } const result = a.reduce( (prev, curr) => ({ cond: [...new Set([...prev.cond, ...curr.cond || []])], matx: [...new Set([...prev.matx, ...curr.matx || []])], work: [...new Set([...prev.work, ...curr.work || []])], }), { cond: [], matx: [], work: [] } ); console.log("Expected cond: ", expectedResult.cond); console.log("Actual cond: ", result.cond); console.log("Expected matx: ", expectedResult.matx); console.log("Actual matx: ", result.cond); console.log("Expected work: ", expectedResult.work); console.log("Actual work: ", result.cond);

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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