How to rearrange array of objects to new array of Objects - javascript

I have an array of objects with the same keys, example:
const data = [{name: "firstName", value: "John"},
{name: "lastName", value: "Smith"},
{name: "Number", value: "421-8686"}
]
I however want the values to become the key and values. example:
const data = [{"firstName": "John"},
{"lastName": "Smith"},
{"Number": "421-8686"}]
I tried a few methods, but for some reason or another I fail. My latest attempt is:
let newData = {}
arrayData.forEach((item, index) => {
let key = data.name
let value = data.value
newData[index] = { key: value} // this results in {"key": "John"} --> but i want {"firstName": "John"}
});

You can use Object.fromEntries.
let data = [
{name: "firstName", value: "John"},
{name: "lastName", value: "Smith"},
{name: "Number", value: "421-8686"}
]
data = data.map(info => Object.fromEntries([[info.name, info.value]]))
console.log(data)

const data = [{name: "firstName", value: "John"},
{name: "lastName", value: "Smith"},
{name: "Number", value: "421-8686"}
]
/*const data = [{"firstName": "John"},
{"lastName": "Smith"},
{"Number": "421-8686"}]
*/
for(let i = 0;i < data.length;i++){
data[i][data[i].name] = data[i].value // creates new key value pair
delete data[i].name // deletes old key
delete data[i].value
}
console.log(data)

let data = [
{ name: "firstName", value: "John" },
{ name: "lastName", value: "Smith" },
{ name: "Number", value: "421-8686" },
];
// map the data to required format.
data = data.map((d) => {
let o = {};
o[d["name"]] = d["value"];
return o;
});
console.log("data",data);

I believe you should get result as following, what you want.
Of course, I confirmed status.
const data = [{name: "firstName", value: "John"},
{name: "lastName", value: "Smith"},
{name: "Number", value: "421-8686"}
]
let newData = [];
data.forEach((item) => {
let obj = {};
obj[item.name] = item.value;
newData.push( obj );
});
console.log(newData);
Thanks.

Just a small tweak to your code. Property has to be dynamically created.
In ES6, we can dynamically create a property key by placing the key in square brackets [].
const data = [
{ name: "firstName", value: "John" },
{ name: "lastName", value: "Smith" },
{ name: "Number", value: "421-8686" }
];
let newData = [];
data.forEach((item, index) => newData[index] = {[item.name]: item.value});
console.log(newData)

Related

How can I create a JavaScript object from an array of objects?

I'm trying to get an array of objects into an object-format with the values as the keys of the new object.
Let's say I got this data:
const data = [
{
key: "foo",
value: "xyz",
classLabel: "Test"
},
{
key: "foo",
value: "abc",
classLabel: "Test"
},
{
key: "bar",
value: "aaa",
classLabel: "Test"
}]
And the format I want to build is like this:
const expected = {
foo: ["xyz", "abc"],
bar: ["aaa"]
}
The values are transferred to the keys and pushed into the same array for duplicate keys.
So far I only extracted the keys with:
const result = [...new Set(data.map(item => item.key))]; // ["foo", "bar"]
const data = [
{
key: "foo",
value: "xyz",
classLabel: "Test"
},
{
key: "foo",
value: "abc",
classLabel: "Test"
},
{
key: "bar",
value: "aaa",
classLabel: "Test"
}];
let expected = data.reduce((out, {key, value}) => {
out[key] = out[key] || [];
out[key].push(value);
return out;
}, {});
console.log(expected);
The following should work:
const data = [
{
key: "foo",
value: "xyz",
classLabel: "Test",
},
{
key: "foo",
value: "abc",
classLabel: "Test",
},
{
key: "bar",
value: "aaa",
classLabel: "Test",
},
];
const mapToObj = (arr) => {
let obj = {};
for (let i in arr) {
let objKey = arr[i].key;
obj[objKey]
? Object.assign(obj, { [arr[i].key]: [obj[objKey], arr[i].value] })
: Object.assign(obj, { [arr[i].key]: arr[i].value });
}
return obj;
};
console.log(mapToObj(data));

Convert array of object with key value pair to a single object? [duplicate]

This question already has answers here:
How do I convert array of Objects into one Object in JavaScript?
(17 answers)
Closed 1 year ago.
I have an array of objects with key-value pair, how to convert it to an object by reducing it to a single object by removing keys. I tried with map filter reduce but couldn't get the desired result. please help
const object = Object.assign({}, ...obj); // not working
const result = {};
Object.keys(object).forEach((key, index) => {
result[`newObj${index + 1}`] = obj[key].map(item => ({[key]: item}));
}); // not working
Input
obj = [{key: name, value: jack},{key: age, value: 10},{key: country, value: india},{key: state, value: Delhi}];
Output
{name:jack, age:10, country:india, state: Delhi}
Use forEach and destructuring
Update: Fixed based on Jan pointed out. Thanks #Jan
obj = [
{ key: "name", value: "jack" },
{ key: "age", value: 10 },
{ key: "country", value: "india" },
{ key: "state", value: "Delhi" },
];
const res = {};
obj.forEach(({ key, value }) => Object.assign(res, { [key]: value }));
console.log(res);
Alternatively, use Object.fromEntries and map
obj = [
{ key: "name", value: "jack" },
{ key: "age", value: 10 },
{ key: "country", value: "india" },
{ key: "state", value: "Delhi" },
];
const res = Object.fromEntries(obj.map(Object.values));
console.log(res);
var obj=[{key: "name", value: "jack"},{key: "age", value: 10},{key: "country", value: "india"},{key: "state", value: "Delhi"}]
var myObj={};
for (var item of obj){
myObj[item.key]=item.value
}
console.log(myObj)
will output
{name: "jack", age: 10, country: "india", state: "Delhi"}
You can use reduce for this:
var input = [
{key: "name", value: "jack"},
{key: "age", value: 10},
{key: "country", value: "India"},
{key: "state", value: "Delhi"},
]
var output = input.reduce((r,{key,value}) => ({[key]:value,...r}),{})
console.log(output)
Output
{ state: 'Delhi', country: 'India', age: 10, name: 'jack' }
The solution uses
object destructuring {key,value}
object spread syntax {...r}
object computed property names {[key]:value}
I think you want like this...
var obj = [
{key: "name", value: "jack"},
{key: "age", value: 10},
{key: "country", value: "india"},
{key: "state", value: "Delhi"}
];
let tempObject = {};
for (let c of obj) {
tempObject[c.key]= c.value;
}
console.log(tempObject);

How to get matched array object based on their values in javascript

I would like to know how to get the array object based on values in javascript.
I have array object obj1, obj2 , how to get the object if name of obj1 matches with obj2 values in javascript
var obj1=[
{name: "country", value: "countries"},
{name: "city", value: "cities"}
]
var obj2=[
{countries:"countries"},
{sample: "sample"}
]
var result = this.getMatchedObj(obj1, obj2);
function getMatchedObj(obj){
const newlist = obj1.map((elem) => obj2.find(e=>Object.values(e)===elem.value));
return newlist;
}
Expected Output:
[
{name: "country", value: "countries"}
]
var obj1=[
{name: "country", value: "countries"},
{name: "city", value: "cities"}
]
var obj2=[
{countries:"countries"},
{sample: "sample"}
]
let data = obj1.filter(ele=>obj2.findIndex(el=> Object.values(el)[0] ==ele.value)!=-1)
console.log(data);
If I understood you correctly, this should work:
var obj1=[
{name: "country", value: "countries"},
{name: "city", value: "cities"}
]
var obj2=[
{countries:"countries"},
{sample: "sample"}
]
function getMatchedObj(obj1, obj2){
const values = obj2.reduce((acc, cur) => acc.concat(Object.values(cur)),[]);
const newlist = obj1.filter(({value}) => values.includes(value));
return newlist;
}
const result = getMatchedObj(obj1, obj2);
console.log(result);
Here's a playground:
https://stackblitz.com/edit/js-6tmjcc
You can can with this:
var obj1=[
{name: "country", value: "countries"},
{name: "city", value: "cities"}
];
var obj2=[
{countries:"countries"},
{sample: "sample"}
];
var item = obj1.find(item => obj2.map(x => Object.values(x)[0]).indexOf(item.value) > -1);
console.log(item);
Get all of the object property values from obj2 to an array. Then making an array to check existing with obj1
Or using for loop:
var obj1=[
{name: "country", value: "countries"},
{name: "city", value: "cities"}
];
var obj2=[
{countries:"countries"},
{sample: "sample"}
];
for (var obj of obj2) {
var values = Object.values(obj);
var item = obj1.find(item => values.indexOf(item.value) > -1);
if (item) {
console.log(item);
}
}
Use filter, find and includes methods.
If you just need one object, Then change filter call to find.
const getMatchedObj = (obj1, obj2) =>
obj1.filter(({ value }) =>
obj2.find((obj) => Object.values(obj).includes(value))
);
var obj1 = [
{ name: "country", value: "countries" },
{ name: "city", value: "cities" },
];
var obj2 = [{ countries: "countries" }, { sample: "sample" }];
console.log(getMatchedObj(obj1, obj2));

Merge 2 arrays of objects with different keys with lodash

I use Backbone/lodash for a project, and I wish merge 2 arrays of objects according to a specific value. With this example below, the merge is based on the same value with 2 different key (id and number).
Example
var people = [
{
id: "1",
name: "John"
},
{
id: "2",
name: "Jane"
}
];
var data = [
{
number: "2",
role: "Designer"
},
{
number: "1",
role: "Developer"
}
];
// Outpout
var merge = [
{
id: "1",
number: "1",
name: "John",
role: "Developer"
},
{
id: "2",
number: "2",
name: "Jane",
role: "Designer"
}
];
_.map(people, function(p){
return _.merge(
p,
_.find(data, {number: p.id})
)
})
I'm not aware of a lodash function that fulfills exactly this use case. However, your goal can be achieved with plain JavaScript and the lodash helpers _.assign() and _.values() pretty well:
var people = [{id: "1", name: "John"}, {id: "2", name: "Jane"}];
var data = [{number: "2", role: "Designer"}, {number: "1", role: "Developer"}];
var resultObj = {};
people.forEach(function(item) {
resultObj[item.id] = item;
});
data.forEach(function(item) {
resultObj[item.number] = _.assign({}, resultObj[item.number], item);
});
var result = _.values(resultObj);
console.log(result);
<script src='https://cdn.jsdelivr.net/lodash/4.17.1/lodash.min.js'></script>
Sort arrays by joining values.
zipWith to zip the arrays together.
defaults to merge each object iterated.
var people = [
{id: "1", name: "John"},
{id: "2", name: "Jane"}
];
var data = [
{number: "2", role: "Designer"},
{number: "1", role: "Developer"}
];
var result = _.zipWith(
_.sortBy(people, person => person.id),
_.sortBy(data, dataItem => dataItem.number),
(person, dataItem) => _.defaults(person, dataItem)
);
console.log(result)
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.1/lodash.min.js"></script>
You can JavaScript to iterate over all your data with Array#map() and do a Array#find() to set all the p object properties where p.id === d.number:
var people = [{id: "1",name: "John"}, {id: "2",name: "Jane"}],
data = [{number: "2",role: "Designer"}, {number: "1",role: "Developer"}],
merge = data.map(d => {
var p = people.find(p => p.id === d.number);
p.number = d.number;
p.role = d.role;
return p;
});
// Outpout
console.log(merge);
.as-console-wrapper { max-height: 100% !important; top: 0; }

Merge JavaScript objects in array with same key

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)

Categories

Resources