I wanted to merge nested javascript object. I was simple when I the length of object was one. But since the lenght has increased I need a dynamic way to merge the address key and serialize my object
var old = {account: "100000", address: {city: "LONDON", companyName: "Test IQUE", country: "UK", postalCode: "SW1A 2AA",}, meterName: "DM9"}
When lenght was 1 this worked for me
var new = {
'account' : "100000",
'address' : "LONDON, UK"
'companyName' : "Test IQUE",
'postalCode' : "SW1A 2AA",
'meterName' : "DM90"
},
{
'account' : "1000001",
'address' : "LONDON, UK"
'companyName' : "Test IQUE",
'postalCode' : "SW1A 2AA",
'meterName' : "DM90"
};
Baiscally I need to serialize my nested address object and merge it into one. As the structure of each object will be same I was thinking of using a for each loop which can combine values of address into one.
If you're asking how you can get a full address string from an addresss object, you can use the following code:
'address': Object.values($scope.userDetails.address).join(', ');
The Object.values() function will change your address object into array.
The .join method will concatenate all of the elements from this array into one string. These elements will be separated by a string passed as an argument (, in this case).
You can use lodash lib : https://lodash.com/docs/4.17.15#assignIn
#see
_.assign(object, [sources])
function Foo() {
this.a = 1;
}
function Bar() {
this.c = 3;
}
Foo.prototype.b = 2;
Bar.prototype.d = 4;
_.assign({ 'a': 0 }, new Foo, new Bar);
// => { 'a': 1, 'c': 3 }
_.mergeWith(object, other, customizer);
function customizer(objValue, srcValue) {
if (_.isArray(objValue)) {
return objValue.concat(srcValue);
}
}
var object = { 'a': [1], 'b': [2] };
var other = { 'a': [3], 'b': [4] };
_.mergeWith(object, other, customizer);
// => { 'a': [1, 3], 'b': [2, 4] }
Related
I'm trying to prepare an object to POST to my server to store some information. This object requires me to do a few GET requests depending on how the user chooses to gather all the information needed to POST. I realized I have to modify the object to actually get them into the correct value pairs in JSON, and I'm not sure if there is a better way to do it.
I'm only showing this in a simple way, but the actual matter has 6-7 very long objects, and they all needs to be modified and fit in one JSON. The server API is written this way to accept input, and I don't have any say in it.
For example:
What I get back from requests
object1: {
id: 1,
name: "table",
price: 3499
}
object2: {
id: 5,
lat: 48.56,
lng: -93.45,
address: "1080 JavaScript Street"
}
What I need it to become:
data: {
map_id: 5,
product_id: [1],
product_name: ["table"],
product_price: [3499],
start_lat: 48.56,
start_lng: -93.45,
start_address: "1080 JavaScript Street"
}
So far I just do the dumb way to just stitch them together, I just wrote this on here so it doesn't work, but should show logically what I'm thinking:
prepareDataToSend = (object1, object2) => {
//exclude uninit handling, and newObject init for arrays
let newObject = {};
newObject.map_id = object2.id;
//if there are more of object1 then I have to loop it
newObject.product_id.push(object1.id);
newObject.product_name.push(object1.name);
...etc
}
I do get the result I'm looking for, but this feels really ineffective and dumb.Not to mention this seems very unmaintainable. Is there a better way to do this? I feel like there is some techniques i'm missing.
You could use ES6 object destructuring.
let object1 = {
id: 1,
name: "table",
price: 3499
};
let object2 = {
id: 5,
lat: 48.56,
lng: -93.45,
address: "1080 JavaScript Street"
};
// declaring the new object with the new properties names.
let newObject = {
map_id: '',
product_id: [],
product_name: [],
product_price: [],
start_lat: '',
start_lng: '',
start_address: ''
};
// destructuring "object1"
({id: newObject.product_id[0],
name: newObject.product_name[0],
price: newObject.product_price[0]} = object1);
// destructuring "object2"
({id: newObject.map_id,
lat: newObject.start_lat,
lng: newObject.start_lng,
address: newObject.start_address} = object2);
console.log(newObject)
Result:
{
map_id: 5,
product_id: [1],
product_name: ["table"],
product_price: [3499],
start_address: "1080 JavaScript Street",
start_lat: 48.56,
start_lng: -93.45
}
It sounds like you need something like JQuery's or Angular's extend() function, but with a twist for sub-mapping the keys.
https://api.jquery.com/jquery.extend/
Here's a simple version of it, tweaked for your needs.
//merge the N objects. Must have a "prefix" property to configure the new keys
var extendWithKeyPrefix = function() {
if (arguments.length == 0) return; //null check
var push = function(dst, arg) {
if (typeof arg != 'undefined' && arg != null) { //null check
var prefix = arg["prefix"]; //grab the prefix
if (typeof prefix != 'undefined' && prefix != null) { //null check
for (var k in arg) { //add everything except for "prefix"
if (k != "prefix") dst[prefix+k] = arg[k];
}
}
}
return dst;
}
arguments.reduce(push);
}
Please note that the value of the last object that uses a particular key will win. For example notice that "id" in the merged object is 2, rather than 1.
var object1 = {id: 1, unique1: "One", prefix: "product_"};
var object2 = {id: 2, unique2: "Two", prefix: "product_"};
var object3 = {id: 3, unique3: "Three", prefix: "office_"};
var merged = {};
extend(merged, object1, object2);
// value of merged is...
// { product_id: 2,
// product_unique1: "One",
// product_unique2: "Two",
// office_id: 3,
// office_unique3: "Three"
// }
I have two Object like this and want to merge them:
const obj1 = {
1: { foo: 1 },
2: { bar: 2, fooBar: 3 },
3: { fooBar: 3 },
};
const obj2 = {
1: { foo: 1, bar: 2 },
2: { bar: 2 },
};
const merged = someMergingMethod(obj1, obj2);
merged === {
1: { foo: 1, bar: 2 },
2: { bar: 2, fooBar: 3 },
3: { fooBar: 3 },
};
I mean, I want to not only merge the objects, but also merge their object values' properties too if the key is duplicated.
Because just merged = { ...obj1, ...obj2 }; overwrites the properties with obj2's.
What is the easiest way to do this?
I can use ES2017 and other libraries like lodash.
You can use spread operator.
Update :
if obj2 has some properties that obj1 does not have?
Initially i wrote this answer assuming the keys are indexed like 0,1 and so on but as you mentioned in comment this is not the case than you can build a array of keys and than iterate over it as
as very concisely added in comment by #Nick [...Object.keys(obj1), ...Object.keys(obj2)]
let obj1 = {1: { foo: 1 },2: { bar: 2, fooBar: 3 },3: { fooBar: 3 },};
let obj2 = {1: { foo: 1, bar: 2 },2: { bar: 2 },};
let keys = [...new Set([...Object.keys(obj1),...Object.keys(obj2)])]
let op = {}
let merged = keys.forEach(key=>{
op[key] = {
...obj1[key],
...obj2[key]
}
})
console.log(op)
Since you mentioned you can use lodash you can use merge like so:
_.merge(obj1, obj2)
to get your desired result.
See working example below:
const a = {
1: { foo: 1 },
2: { bar: 2, fooBar: 3 },
3: { fooBar: 3 },
},
b = {
1: { foo: 1, bar: 2 },
2: { bar: 2 },
4: {foo: 1}
},
res = _.merge(a, b);
console.log(res);
<script src="https://cdn.jsdelivr.net/lodash/4.16.4/lodash.min.js"></script>
I have exactly what you want.
This function will traverse through each nested object and combine it with the other. I've only tested it with 5 nested levels down the tree but, theoretically, it should work for any number of nested objects as it is a recursive function.
//this function is similar to object.assign but,
//leaves the keys which are common among both bojects untouched
function merge(object1, object2)
{
function combine(p, q)
{
for(i in q)
if(!p.hasOwnProperty(i))
p[i]= q[i];
return p;
}
obj1= Object.assign(combine(obj1, obj2), obj1);//for the first level
obj1= Object.assign(traverse(obj1, obj2), obj1);//for subsequent levels down theobjectt tree
//this function traverses each nested boject and combines it with the other object
function traverse(a, b)
{
if(typeof(a) === "object" && typeof(b) === "object")
for(i in b)
if(typeof(a[i]) === "object" && typeof(b[i]) === "object")
a[i]= Object.assign(traverse(a[i], b[i]), a[i]);
else
Object.assign(combine(a, b), a);
return a;
}
return obj1;
}
console.log(merge(obj1, obj2));
Here is a working example of a much more complex object merging
var obj1 = {
1: { foo: 1 },
2: { bar: 2, fooBar: 3 },
3: { fooBar: 3, boor:{foob: 1, foof: 8} },
4: {continent: {
asia: {country: {india: {capital: "delhi"}, china: {capital: "beiging"}}},
europe:{country:{germany: {capital: "berlin"},france: {capital: "paris"}}}
},
vegtables: {cucumber: 2, carrot: 3, radish: 7}
}
};
var obj2 = {
1: { foo: 1, bar: 2 },
2: { bar: 2 },
3: {fooBar: 3, boor:{foob: 1, boof: 6}, boob: 9 },
4: {continent: {
northamerica: {country: {mexico: {capital: "mexico city"}, canada: {capital: "ottawa"}},},
asia: {country: {Afghanistan : {capital: "Kabul"}}}
}
},
5: {barf: 42}
};
//this function is similar to object.assign but,
//leaves the keys which are common among both bojects untouched
function merge(object1, object2)
{
function combine(p, q)
{
for(i in q)
if(!p.hasOwnProperty(i))
p[i]= q[i];
return p;
}
obj1= Object.assign(combine(obj1, obj2), obj1);//for the first level
obj1= Object.assign(traverse(obj1, obj2), obj1);//for subsequent levels down the object tree
//this function traverses each nested boject and combines it with the other object
function traverse(a, b)
{
if(typeof(a) === "object" && typeof(b) === "object")
for(i in b)
if(typeof(a[i]) === "object" && typeof(b[i]) === "object")
a[i]= Object.assign(traverse(a[i], b[i]), a[i]);
else
Object.assign(combine(a, b), a);
return a;
}
return obj1;
}
console.log(merge(obj1, obj2));
you can use Object.assign and and assign object properties to empty object.
var a = {books: 2};
var b = {notebooks: 1};
var c = Object.assign( {}, a, b );
console.log(c);
or
You could use merge method from Lodash library.
can check here :
https://www.npmjs.com/package/lodash
Are you looking like this?
we can use this way to merge two objects.
const person = { name: 'David Walsh', gender: 'Male' };
const attributes = { handsomeness: 'Extreme', hair: 'Brown', eyes: 'Blue' };
const summary = {...person, ...attributes};
/*
Object {
"eyes": "Blue",
"gender": "Male",
"hair": "Brown",
"handsomeness": "Extreme",
"name": "David Walsh",
}
*/
This can be easily accomplished with a combination of the neat javascript spread syntax, Array and Object prototype functions, and destructuring patterns.
[obj1,obj2].flatMap(Object.entries).reduce((o,[k,v])=>({...o,[k]:{...o[k],...v}}),{})
As simple as this!
For a very detailed explanation of how this works, refer to this extended answer to a similar question.
Hello I am struggling with arrays in JavaScript/NodeJS.
Basically, here is my code:
let arr = new Array();
arr = {
"Username" : var1,
"Console" : var2,
"Pseudo" : var3,
}
console.log(arr);
var1, 2 and 3 contains my data that is changing each time.
Let's consider for our first case:
var1 is "Johnson"
var2 is "ps4"
var3 is "Johnson46"
The code above would display the following:
{ Username: 'Johnson', Console: 'ps4', Pseudo: 'Johnson46' }
Now if the data in var1, var2, and var3 change, it will replace the array's content with new data. So if var1 = "Dave", var2 = "xbox" and var3 = "Dave78", it will replace the current array and display:
{ Username: 'Dave', Console: 'xbox', Pseudo: 'Dave78' }
But instead I would like my code to print the follwing:
{ Username: 'Johnson', Console: 'ps4', Pseudo: 'Johnson46' }
{ Username: 'Dave', Console: 'xbox', Pseudo: 'Dave78' }
See? Without overriding the array, just adding my data in succession. "line by line" or "step by step" if you prefer, sorry I don't really know how to say that.
You must push your objects to the array instead modifying it
let arr = new Array();
object1 = {
"Username" : "Jhon",
"Console" : "xbox",
"Pseudo" : "asd",
}
arr.push(object1)
object2 = {
"Username" : "Doe",
"Console" : "ps4",
"Pseudo" : "efg",
}
arr.push(object2)
console.log(arr);
I am going for more of a theoretical route. Maybe it will clear some of your doubt maybe it will not.
First of all, on a side note, Even though Array is technically an object but {..} is the notation for objects not arrays. If there is a object like {'0':.., '1':.., '2':..} and it has a length property then is called an array like object (thanks #Alnitak)
Now, when you are declaring an object, and adding values from variables if you're referencing an immutable object like string, number it will reference the value itself. If you're referencing say an object it will hold the object's reference and if you change the object it will change too.
For example:
const obj = {'a':'b'};
const x = {
m: obj.a
}
console.log(x);
obj.a = 'c';
console.log(x);
This will print,
{ m: 'b' }
{ m: 'b' }
But when your code is:
const obj = {'a':'b'};
const x = {
m: obj //referencing obj
}
console.log(x);
obj.a = 'c';
console.log(x);
It will print:
{ m: { a: 'b' } }
{ m: { a: 'c' } }
So, if you want your code to just print it then you can reference an object in your variable.
I have a object like this.
var Obj = {
obj1 : {
val : 1,
id : 1
}
obj2 : {
val : 2,
id :2
}
obj3 : {
val : 3,
id :3
}
}
I want my obj1and all sub object into one array so I can retrieve the value. I want array in array because I want to retrieve them, Since it is dynamic I can not use Obj.obj1 therefore I want to push into array.
Can Anybody tell How Can I get that. Thanks for help
Use Object.keys and Array#map methods to convert it to an array but the order is not guaranteed since object properties don't have any order.
var Obj = {
obj1: {
val: 1,
id: 1
},
obj2: {
val: 2,
id: 2
},
obj3: {
val: 3,
id: 3
}
};
var res = Object.keys(Obj).map(function(k) {
return Obj[k];
})
console.log(res);
I have:
var obj = {'a': {some object}, 'b': {some other object}, 'c':{some other object},...}
I want to write a function that will overwrite any single key in my original object.
myFunction(obj, {'a': {new object}});
console.log(obj);
//{'a': {new object}, 'b': {some other object}, 'c':{some other object},...}
I am using lodash. I obviously know that I can do _.keys then get the only item in the array and then assign it manually but I wonder if there is a less cumbersome way.
The _.extend function, available as Object.assign in ES6-compatible Javascript, does what you want.
_.extend({ a: 1, b: 2 }, { a: 10 })
// { a: 10, b: 2 }
The function is more flexible than simple assignment: you can add or replace any number of keys, shallow-merging the objects passed as parameters.
No need of Lodash/Underscore, this can be done in JavaScript easily.
obj[key] = newObject;
var obj = {
one: {
1: 'ONE'
},
two: {
2: 'TWO'
},
three: {
3: 'THREE'
}
};
obj['two'] = {
22: 'Two Two'
};
console.log(obj);
UPDATE:
You can use Object.assign()
Object.assign(obj, {
two: {
22: 'Two Two'
}
});