Related
I am trying to place my _rows values into my object value , however i have tried running a loop but i wasnt able to get the data out , the script i used is
let _columns = ["Name", "age", "phone"]
let _rows = [[{ value: 'john' }, { value: '22' }, { value: '999' }], [{ value: 'Bob' }, { value: '21' }, { value: '222' }]]
let res = {}
for (let i = 0; i < _rows.length; i++) {
for (let a = 0; a < _columns.length; a++) {
console.log(_rows[i][a].value)
}
res = _columns.reduce((acc,curr)=> (acc[curr]="data",acc),{});
console.log(res)
res = {}
}
on my console.log , it prints
The target output should be
{Name: 'john', age: '22', phone: '999'}
{Name: 'bob', age: '21', phone: '222'}
you can use
array.map to build another array from _rows
foreach value you have to check if columns exist
if (_columns[index]) {
if yes add in the new object the value under column name
res[_columns[index]] = property.value;
let _columns = ["Name", "age", "phone"]
let _rows = [[{ value: 'john' }, { value: '22' }, { value: '999' }], [{ value: 'Bob' }, { value: '21' }, { value: '222' }]];
let result = _rows.map(one => {
let res = {};
one.forEach((property, index) => {
if (_columns[index]) {
res[_columns[index]] = property.value;
}
});
return res;
});
console.log(result);
If you want to stick with reduce, just make this small change to get the actual value instead of the hardcode string "data". You need to use the optional parameter currentIndex of the reduce callback, then use the index to access the row item for the value.
let _columns = ["Name", "age", "phone"]
let _rows = [[{ value: 'john' }, { value: '22' }, { value: '999' }], [{ value: 'Bob' }, { value: '21' }, { value: '222' }]]
let res = {}
for (let i = 0; i < _rows.length; i++) {
for (let a = 0; a < _columns.length; a++) {
console.log(_rows[i][a].value)
}
res = _columns.reduce((acc,curr,index)=> (acc[curr]=_rows[i][index].value,acc),{});
console.log(res)
res = {}
}
However, when dealing with rows and columns in your case, since the array index is important, using old-school nested for-loop might be much more clear sometimes. My experience is, when you need the array index anyway, try not to be fancy and go for regular for-loop.
let _columns = ["Name", "age", "phone"]
let _rows = [[{ value: 'john' }, { value: '22' }, { value: '999' }], [{ value: 'Bob' }, { value: '21' }, { value: '222' }]]
for(let i = 0; i < _rows.length; i++)
{
let res = {};
for(let j = 0; j < _columns.length; j++)
{
res[_columns[j]] = _rows[i][j].value
}
console.log(res);
}
A double Arry.map will do the trick
let _columns = ["Name", "age", "phone"]
let _rows = [
[{ value: 'john' }, { value: '22' }, { value: '999' }],
[{ value: 'Bob' }, { value: '21' }, { value: '222' }]
];
const output = _rows.map((row) => row.map((item, index) => ({ [_columns[index]]: item.value })));
console.log(output)
I have the following array
var array = [
{
group: "FL",
list: [
{ key: "A", value: "Alaska" },
{ key: "B", value: "Brazil" },
{ key: "C", value: "California" }
]
},
{
group: "NZ",
list: [
{ key: "A", value: "Alaska" },
{ key: "B", value: "Brazil" },
{ key: "D", value: "Delhi" }
]
},
{
group: "QA",
list: [
{ key: "A", value: "Alaska" },
{ key: "B", value: "Brazil" },
{ key: "C", value: "California" }
]
}
]
I need to check the list array and if all the objects in the list array are exately same , then I need to merge it as below:
[
{
group: "FL,QA",
list: [
{ key: "A", value: "Alaska" },
{ key: "B", value: "Brazil" },
{ key: "C", value: "California" }
]
},
{
group: "NZ",
list: [
{ key: "A", value: "Alaska" },
{ key: "B", value: "Brazil" },
{ key: "D", value: "Delhi" }
]
}
]
I tried this by using reduce method to loop over the array and two other functions to compare the objects, but somehow its not working
array.reduce(async(acc, item) => {
const exist = await compareObjects(acc, item);
if (exist) {
acc[exist.index].group= exist.group + ',' + item.group;
} else {
acc.push(item)
}
return acc;
}, [])
async function compareObjects(o1, o2) {
for (let i = 0; i < o1.length; i++) {
const value = await checkObjs(o1[i].list, o2.list);
if(value) { return {index:i , group: o1[i].group} }
}
}
function checkObjs(arr1, arr2) {
return arr1.length === arr2.length && arr1.every((el, i) => objectsEqual(el, arr2[i]))
}
const objectsEqual = (o1, o2) =>
Object.keys(o1).length === Object.keys(o2).length
&& Object.keys(o1).every(p => o1[p] === o2[p]);
Any help would be appreciated . Thanks
Your use of async is what's tripping you up here, and I'm not sure your reason for using it.
To make your code work as is you need to await the accumulator on each iteration, and assign the result of the reduce() to something.
var array = [ { group: 'FL', list: [ { key: 'A', value: 'Alaska' }, { key: 'B', value: 'Brazil' }, { key: 'C', value: 'California' }, ], }, { group: 'NZ', list: [ { key: 'A', value: 'Alaska' }, { key: 'B', value: 'Brazil' }, { key: 'D', value: 'Delhi' }, ], }, { group: 'QA', list: [ { key: 'A', value: 'Alaska' }, { key: 'B', value: 'Brazil' }, { key: 'C', value: 'California' }, ], }, ];
function checkObjs(arr1, arr2) {
const objectsEqual = (o1, o2) =>
Object.keys(o1).length === Object.keys(o2).length && Object.keys(o1).every((p) => o1[p] === o2[p]);
return arr1.length === arr2.length && arr1.every((el, i) => objectsEqual(el, arr2[i]));
}
async function compareObjects(o1, o2) {
for (let i = 0; i < o1.length; i++) {
const value = await checkObjs(o1[i].list, o2.list);
if (value) {
return { index: i, group: o1[i].group };
}
}
}
// assign the result of reduce to a variable
const result = array.reduce(async (acc, item) => {
acc = await acc; // await the returned accumulator Promise
const exist = await compareObjects(acc, item);
if (exist) {
acc[exist.index].group = exist.group + ',' + item.group;
} else {
acc.push(item);
}
return acc;
}, []);
result.then((r) => console.log(r));
.as-console-wrapper { max-height: 100% !important; top: 0; }
You can use Array.reduce() to create a map of your input objects.
We'll create a function getListKey() to create a unique key based on each object list.
Once we have our map, we can use Object.values() to get the array result:
var array = [ { group: "FL", list: [ { key: "A", value: "Alaska" }, { key: "B", value: "Brazil" }, { key: "C", value: "California" } ] }, { group: "NZ", list: [ { key: "A", value: "Alaska" }, { key: "B", value: "Brazil" }, { key: "D", value: "Delhi" } ] }, { group: "QA", list: [ { key: "A", value: "Alaska" }, { key: "B", value: "Brazil" }, { key: "C", value: "California" } ] } ]
function getListKey(list) {
return JSON.stringify(list.sort(({ key: a }, { key: b }) => a.localeCompare(b)));
}
const result = Object.values(array.reduce((acc, { group, list }) => {
const key = getListKey(list);
if (!acc[key]) {
acc[key] = { group, list };
} else {
acc[key].group += "," + group;
}
return acc;
}, {}))
console.log('Result:', result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
Another way of approaching this is again using Array.reduce(), but using the lodash _.isEqual() function for list comparison. This performs a deep comparison. We'd use this along with Array.find() to get any list duplicate.
var array = [ { group: "FL", list: [ { key: "A", value: "Alaska" }, { key: "B", value: "Brazil" }, { key: "C", value: "California" } ] }, { group: "NZ", list: [ { key: "A", value: "Alaska" }, { key: "B", value: "Brazil" }, { key: "D", value: "Delhi" } ] }, { group: "QA", list: [ { key: "A", value: "Alaska" }, { key: "B", value: "Brazil" }, { key: "C", value: "California" } ] } ]
const result = array.reduce((acc, cur) => {
const foundItem = acc.find(item => _.isEqual(item.list, cur.list));
if (foundItem) {
foundItem.group += `,${cur.group}`;
} else {
acc.push(cur);
}
return acc;
}, [])
console.log('Result:', result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.21/lodash.min.js" referrerpolicy="no-referrer"></script>
I think the way I would suggest going about this problem is by breaking it apart and (hopefully) using library functions to tackle some of the more complicated bits. For example with lodash you could say
import isEqual from "lodash/isEqual";
const arr = [
{
group: "FL",
list: [
{ key: "A", value: "Alaska" },
{ key: "B", value: "Brazil" },
{ key: "C", value: "California" }
]
},
{
group: "NZ",
list: [
{ key: "A", value: "Alaska" },
{ key: "B", value: "Brazil" },
{ key: "D", value: "Delhi" }
]
},
{
group: "QA",
list: [
{ key: "A", value: "Alaska" },
{ key: "B", value: "Brazil" },
{ key: "C", value: "California" }
]
}
];
function groupBy<T, R>(
a: T[],
iteritem: (t: T) => R,
compare: (a: R, b: R) => boolean = isEqual
) {
const groups: T[][] = [];
const rs = a.map(iteritem);
for (let i = 0; i < rs.length; i++) {
let added = false;
const r = rs[i];
for (let j = 0; j < groups.length; j++) {
if (compare(r, iteritem(groups[j][0]))) {
groups[j].push(a[i]);
added = true;
break;
}
}
if (!added) {
groups.push([a[i]]);
}
}
return groups;
}
const grouped = groupBy(arr, (a) => a.list);
const combined = [];
for (const g of grouped) {
combined.push({
group: g.map(({ group }) => group).join(","),
list: g[0].list
});
}
console.log(JSON.stringify(combined, undefined, 2));
This isn't as much of a one off answer since groupBy could be reused. I originally wanted to use groupBy from lodash but it doesn't accept a custom equality function.
This is one possible solution:
const sorted = [];
for (let i = 0; i < groups.length; i++) {
const identicalLists = [];
for (let j = i; j < groups.length; j++) {
const isIdentical =
JSON.stringify(groups[i].list) === JSON.stringify(groups[j].list);
const found = !!sorted.flat().find((item) => item === groups[j].group);
if (isIdentical && !found) {
identicalLists.push(groups[j].group);
}
}
if (identicalLists.length > 0) {
sorted.push(identicalLists);
}
}
const answer = sorted.map((item) => {
const first = groups.find((group) => group.group === item[0]);
return { group: item, list: first.list };
});
Reduce does not work with async/await. If you don't have async code - one that fetches something from an API or uses data from a Promise, you should remove the async/await, because it is synchronous.
If the code you have uses some async API - try using something like:
export const reduceAsync = async (array, transformer, initialvalue) => {
let accumolator = typeof initialValue !== 'undefined' ? initialValue : array[0];
for (let i = 0; i < array.length; i++) {
accumolator = await transformer(accumolator, array[i], i, array);
}
return accumolator;
};
The function above is reusable and follows the spec defined here: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/Reduce
I want to remove each copy of object from array:
const object = [
{ label: "SUA", value: "sua" },
{ label: "SUA", value: "sua" },
{ label: "Florida", value: "florida" }
];
console.log(object.map(i=> [...new Set(i)]))
At the end i have to get like:
const object = [
{ label: "Florida", value: "florida" }
];
How to do this in my code?
You can use 2 for loops to achieve your functionality.
let result = [];
for(let i=0;i<object.length ;i++) {
let isDuplicate = false;
for(let j=0; j<object.length;j++) {
if(object[i].label === object[j].label && object[i].value === object[j].value && i !== j) {
isDuplicate = true;
}
}
if(!isDuplicate) result.push(object[i]);
}
Regardless of how many copies of each element you'd like to keep in the array, create a Map by definition Map<Location, number> and tabulate the number of occurrences of each Location object. Afterwards, take each element and append it to an array only once.
type Location = {label: string, value: string};
const object: Location[] = [
{ label: "SUA", value: "sua" },
{ label: "SUA", value: "sua" },
{ label: "Florida", value: "florida" }
];
const objects: Map<Location, number> = new Map();
for (const location of object)
if (objects.has(location))
objects.set(location, objects.get(location) + 1);
else
objects.set(location, 1);
const filtered: Location[] = [];
for (const location of objects)
if (location[1] === 1) // You change 1 to any value depending on how many copies of each you'd like.
filtered.push(location[0];
Note This is TypeScript for clarity, but the concept is the same.
You can use ES6 set -
const unique = [...new Set(object.map(({value}) => value))].map(e => object.find(({value}) => value == e));
console.log("unique",unique);
//[{label: "SUA", value: "sua"},{label: "Florida", value: "florida"}]
for your problem you can simply use reduce -
const uniq = object.reduce((a,b)=>{return a.value === b.value ? {} :[b]},[])
console.log(uniq);
//[{label: "Florida", value: "florida"}]
Short way:
const object = [
{ label: "SUA", value: "sua" },
{ label: "SUA", value: "sua" },
{ label: "Florida", value: "florida" }
];
const a = object.filter((v, i, a) => a.findIndex(t => (t.label ===
v.label && t.value === v.value)) === i);
console.log(a);
Simple solution with lodash
const object = [
{ label: "SUA", value: "sua" },
{ label: "SUA", value: "sua" },
{ label: "Florida", value: "florida" }
];
result = _.xor(_.uniqWith(object,_.isEqual),object)
I'm trying to turn a dot notation string into an object, for example given
[{
key: 'app.team.instance',
value: 'some value1'
}, {
key: 'app.team.instance.obj',
value: 'some value'
}, {
key: 'app.team.app.some',
value: 'some value'
}, {
key: 'app.service.awesome.more',
value: 'more values'
}]
I would like to turn it an object like to get
{
"team": {
"instance": "some value1",
"server": {
"obj": "some value"
},
"app": {
"some": "some value"
}
},
"service": {
"awesome": {
"more": "more values"
}
}
}
This's what I have tried using the following function. Looking at my function what have I missed or should improve?
function createObjFromRows(skip, key, value, obj) {
const ARRAY_KEYS = key.split('.');
const ARRAY_LENGTH = ARRAY_KEYS.length;
let i = skip ? 1 : 0;
for (; i < ARRAY_LENGTH; i++) {
if (i < (ARRAY_LENGTH - 1)) {
if (!obj.hasOwnProperty(ARRAY_KEYS[i])) { obj[ARRAY_KEYS[i]] = {}; }
} else {
obj[ARRAY_KEYS[i - 1]][ARRAY_KEYS[i]] = value;
}
}
}
This's what I get currently.
{
team: {
instance: 'some value1'
},
server: {
obj: 'some value'
},
app: {
some: 'some value'
},
service: {},
awesome: {
more: 'more values'
}
}
You can use array.prototype.reduce :
var datas = [ {key: 'app.team.instance', value: 'some value1'}, {key: 'app.team.server.obj', value: 'some value'}, {key: 'app.team.app.some',value: 'some value'}, {key: 'app.service.awesome.more', value: 'more values'}];
var res = datas.reduce((m, o) => {
var keys = o.key.split('.');
var cur = m;
keys.forEach((key, i) => {
if (i < keys.length - 1) {
cur[key] = cur[key] || {};
cur = cur[key];
} else {
cur[key] = o.value;
}
});
return m;
}, {});
console.log(res);
You could split the given key strings and save the last key for the assignment of the value after iterating the keys to the nested property.
var data = [{ key: 'app.team.instance', value: 'some value1' }, { key: 'app.team.server.obj', value: 'some value' }, { key: 'app.team.app.some', value: 'some value' }, { key: 'app.service.awesome.more', value: 'more values' }],
result = data.reduce(function (r, o) {
var path = o.key.split('.'),
last = path.pop();
path.reduce(function (p, k) {
return p[k] = p[k] || {};
}, r)[last] = o.value;
return r;
}, {});
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
What is the best way to merge array contents from JavaScript objects sharing a key in common?
How can array in the example below be reorganized into output? Here, all value keys (whether an array or not) are merged into all objects sharing the same name key.
var array = [
{
name: "foo1",
value: "val1"
}, {
name: "foo1",
value: [
"val2",
"val3"
]
}, {
name: "foo2",
value: "val4"
}
];
var output = [
{
name: "foo1",
value: [
"val1",
"val2",
"val3"
]
}, {
name: "foo2",
value: [
"val4"
]
}
];
Here is one option:-
var array = [{
name: "foo1",
value: "val1"
}, {
name: "foo1",
value: ["val2", "val3"]
}, {
name: "foo2",
value: "val4"
}];
var output = [];
array.forEach(function(item) {
var existing = output.filter(function(v, i) {
return v.name == item.name;
});
if (existing.length) {
var existingIndex = output.indexOf(existing[0]);
output[existingIndex].value = output[existingIndex].value.concat(item.value);
} else {
if (typeof item.value == 'string')
item.value = [item.value];
output.push(item);
}
});
console.dir(output);
Here is another way of achieving that goal:
var array = [{
name: "foo1",
value: "val1"
}, {
name: "foo1",
value: [
"val2",
"val3"
]
}, {
name: "foo2",
value: "val4"
}];
var output = array.reduce(function(o, cur) {
// Get the index of the key-value pair.
var occurs = o.reduce(function(n, item, i) {
return (item.name === cur.name) ? i : n;
}, -1);
// If the name is found,
if (occurs >= 0) {
// append the current value to its list of values.
o[occurs].value = o[occurs].value.concat(cur.value);
// Otherwise,
} else {
// add the current item to o (but make sure the value is an array).
var obj = {
name: cur.name,
value: [cur.value]
};
o = o.concat([obj]);
}
return o;
}, []);
console.log(output);
2021 version
Using reduce to aggregate data.
Using logical nullish assignment only assigns if acc[name] is nullish (null or undefined).
Using Array.isArray to determines whether the passed value is an Array.
var arrays = [{ name: "foo1",value: "val1" }, {name: "foo1", value: ["val2", "val3"] }, {name: "foo2",value: "val4"}];
const result = arrays.reduce((acc, {name, value}) => {
acc[name] ??= {name: name, value: []};
if(Array.isArray(value)) // if it's array type then concat
acc[name].value = acc[name].value.concat(value);
else
acc[name].value.push(value);
return acc;
}, {});
console.log(Object.values(result));
Using lodash
var array = [{name:"foo1",value:"val1"},{name:"foo1",value:["val2","val3"]},{name:"foo2",value:"val4"}];
function mergeNames (arr) {
return _.chain(arr).groupBy('name').mapValues(function (v) {
return _.chain(v).pluck('value').flattenDeep();
}).value();
}
console.log(mergeNames(array));
Here is a version using an ES6 Map:
const arrays = [{ name: "foo1",value: "val1" }, {name: "foo1", value: ["val2", "val3"] }, {name: "foo2",value: "val4"}];
const map = new Map(arrays.map(({name, value}) => [name, { name, value: [] }]));
for (let {name, value} of arrays) map.get(name).value.push(...[value].flat());
console.log([...map.values()]);
Use lodash "uniqWith". As shown below
let _ = require("lodash");
var array = [
{ name: "foo1", value: "1" },
{ name: "foo1", value: "2" },
{ name: "foo2", value: "3" },
{ name: "foo1", value: "4" }
];
let merged = _.uniqWith(array, (pre, cur) => {
if (pre.name == cur.name) {
cur.value = cur.value + "," + pre.value;
return true;
}
return false;
});
console.log(merged);
// output: [{ name: "foo1", value: "1,2,4" }, { name: "foo2", value: "3" }];
Using reduce:
var mergedObj = array.reduce((acc, obj) => {
if (acc[obj.name]) {
acc[obj.name].value = acc[obj.name].value.isArray ?
acc[obj.name].value.concat(obj.value) :
[acc[obj.name].value].concat(obj.value);
} else {
acc[obj.name] = obj;
}
return acc;
}, {});
let output = [];
for (let prop in mergedObj) {
output.push(mergedObj[prop])
}
It's been a while since this question was asked, but I thought I'd chime in as well. For functions like this that execute a basic function you'll want to use over and over, I prefer to avoid longer-written functions and loops if I can help it and develop the function as a one-liner using shallow Array.prototype functions like .map() and some other ES6+ goodies like Object.entries() and Object.fromEntries(). Combining all these, we can execute a function like this relatively easily.
First, I take in however many objects you pass to the function as a rest parameter and prepend that with an empty object we'll use to collect all the keys and values.
[{}, ...objs]
Next, I use the .map() Array prototype function paired with Object.entries() to loop through all the entries of each object, and any sub-array elements each contains and then either set the empty object's key to that value if it has not yet been declared, or I push the new values to the object key if it has been declared.
[{},...objs].map((e,i,a) => i ? Object.entries(e).map(f => (a[0][f[0]] ? a[0][f[0]].push(...([f[1]].flat())) : (a[0][f[0]] = [f[1]].flat()))) : e)[0]
Finally, to replace any single-element-arrays with their contained value, I run another .map() function on the result array using both Object.entries() and Object.fromEntries(), similar to how we did before.
let getMergedObjs = (...objs) => Object.fromEntries(Object.entries([{},...objs].map((e,i,a) => i ? Object.entries(e).map(f => (a[0][f[0]] ? a[0][f[0]].push(...([f[1]].flat())) : (a[0][f[0]] = [f[1]].flat()))) : e)[0]).map(e => e.map((f,i) => i ? (f.length > 1 ? f : f[0]) : f)));
This will leave you with the final merged object, exactly as you prescribed it.
let a = {
a: [1,9],
b: 1,
c: 1
}
let b = {
a: 2,
b: 2
}
let c = {
b: 3,
c: 3,
d: 5
}
let getMergedObjs = (...objs) => Object.fromEntries(Object.entries([{},...objs].map((e,i,a) => i ? Object.entries(e).map(f => (a[0][f[0]] ? a[0][f[0]].push(...([f[1]].flat())) : (a[0][f[0]] = [f[1]].flat()))) : e)[0]).map(e => e.map((f,i) => i ? (f.length > 1 ? f : f[0]) : f)));
getMergedObjs(a,b,c); // { a: [ 1, 9, 2 ], b: [ 1, 2, 3 ], c: [ 1, 3 ], d: 5 }
Try this:
var array = [{name:"foo1",value:"val1"},{name:"foo1",value:["val2","val3"]},{name:"foo2",value:"val4"},{name:"foo2",value:"val5"}];
for(var j=0;j<array.length;j++){
var current = array[j];
for(var i=j+1;i<array.length;i++){
if(current.name = array[i].name){
if(!isArray(current.value))
current.value = [ current.value ];
if(isArray(array[i].value))
for(var v=0;v<array[i].value.length;v++)
current.value.push(array[i].value[v]);
else
current.value.push(array[i].value);
array.splice(i,1);
i++;
}
}
}
function isArray(myArray) {
return myArray.constructor.toString().indexOf("Array") > -1;
}
document.write(JSON.stringify(array));
This work too !
var array = [
{
name: "foo1",
value: "val1",
},
{
name: "foo1",
value: ["val2", "val3"],
},
{
name: "foo2",
value: "val4",
},
];
let arr2 = [];
array.forEach((element) => { // remove duplicate name
let match = arr2.find((r) => r.name == element.name);
if (match) {
} else {
arr2.push({ name: element.name, value: [] });
}
});
arr2.map((item) => {
array.map((e) => {
if (e.name == item.name) {
if (typeof e.value == "object") { //lets map if value is an object
e.value.map((z) => {
item.value.push(z);
});
} else {
item.value.push(e.value);
}
}
});
});
console.log(arr2);
const exampleObj = [{
year: 2016,
abd: 123
}, {
year: 2016,
abdc: 123
}, {
year: 2017,
abdcxc: 123
}, {
year: 2017,
abdcxcx: 123
}];
const listOfYears = [];
const finalObj = [];
exampleObj.map(sample => {
listOfYears.push(sample.year);
});
const uniqueList = [...new Set(listOfYears)];
uniqueList.map(list => {
finalObj.push({
year: list
});
});
exampleObj.map(sample => {
const sampleYear = sample.year;
finalObj.map((obj, index) => {
if (obj.year === sampleYear) {
finalObj[index] = Object.assign(sample, obj);
}
});
});
The final object be [{"year":2016,"abdc":123,"abd":123},{"year":2017,"abdcxcx":123,"abdcxc":123}]
const array = [{ name: "foo1", value: "val1" }, {name: "foo1", value: ["val2", "val3"] }, {name: "foo2", value: "val4"}];
const start = array.reduce((object, {name}) => ({...object, [name]: []}), {});
const result = array.reduce((object, {name, value}) => ({...object, [name]: [object[name], [value]].flat(2)}), start);
const output = Object.entries(result).map(([name, value]) => ({name: name, value: value}));
console.log(output);
try this :
var array = [
{
name: "foo1",
value: "val1"
}, {
name: "foo1",
value: [
"val2",
"val3"
]
}, {
name: "foo2",
value: "val4"
}
];
var output = [
{
name: "foo1",
value: [
"val1",
"val2",
"val3"
]
}, {
name: "foo2",
value: [
"val4"
]
}
];
bb = Object.assign( {}, array, output );
console.log(bb) ;
A much more easier approach is this 2022:
var array = [
{
name: "foo1",
value: "val1"
}, {
name: "foo1",
value: [
"val2",
"val3"
]
}, {
name: "foo2",
value: "val4"
}
];
var output = [
{
name: "foo1",
value: [
"val1",
"val2",
"val3"
]
},
{
name: "foo2",
value: [
"val4"
]
}
];
function mergeBasedOnKey(list){
let c = Object.values(list.reduce((a, b) => {
a[b.name] = a[b.name] || {name: b.name, value: []}
if(typeof(b['value']) == "string"){
a[b.name].value.push(b['value'])
}
else{
a[b.name].value = [...a[b.name].value, ...b.value]
}
return a
}, {}))
return c
}
let ans = mergeBasedOnKey(array)
console.log(ans)
I was looking for a quick, almost "one-liner" answer in this thread, provided that this is a trivial but common exercise.
I couldn't find any for my like. The other answers are fine but I am not much into boilerplate.
So, let me add one, then:
o = array.reduce((m,{name:n,value:v})=>({...m,[n]:[...m[n]||[],v].flat(1)}),{})
output = Object.entries(o).map(([n,v])=>({name:n,value:v}))
var array = [
{ name: "foo1", value: "val1"},
{ name: "foo1", value: ["val2","val3"] },
{ name: "foo2", value: "val4" }
]
o=array.reduce((m,{name:n,value:v})=>({...m,[n]:[...m[n]||[],v].flat(1)}),{})
output=Object.entries(o).map(([n,v])=>({name:n,value:v}))
console.log(output)