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.