Is there any way to merge two objects, like Object.assign(a, b), but I want the same field in a keeps its origin value (without overriding from b).
a = {x: 1, y: 2}
b = {y: 3, z: 4}
Object.assign(a, b)
// Now we get a = {x: 1, y: 3, z: 4}, so what if I want {x: 1, y: 2, z: 4}?
console.log(a)
Note: thanks for the efforts from the answers, the key requirements for the question is:
modify a
not too much code
not too slow
To modify the a reference (like you seem to be wanting to do from your example), you could do:
const a = {x: 1, y: 2};
const b = {y: 3, z: 4};
Object.assign(a, {...b, ...a});
console.log(a);
This essentially says, replace the overlapping properties in b with those from a, and then merge this replaced object into a.
Above, the {...b, ...a} first merges a with b, so a overwrites properties in b, giving us:
{y: 3, z: 4, x: 1, y: 2}
// evalutes to
{z: 4, x: 1, y: 2}
Now we merge this result into a with the Object.assign() call:
{x: 1, y: 2, z: 4, x: 1, y: 2}
// evalutes to
{z: 4, x: 1, y: 2}
// ie:
{x: 1, y: 2, z: 4}
Edit:
To meet your requirements, use a regular for...in loop, it's efficient, doesn't require much code (especially if you remove the blocks), and modifies a:
const a = {x: 1, y: 2};
const b = {y: 3, z: 4};
for(const key in b) a[key] ??= b[key];
console.log(a); // {"x": 1, "y": 2, "z": 4}
The above works if your values won't be nullish (null/undefined) as it uses logical nullish assignment (??=), otherwise, you can replace the assignment with:
a[key] = key in a ? a[key] : b[key];
The best solution to this is to avoid using Object.assign and use spread operator as by doing so you'll achieve your goal with simple logic. In spread operator, the rightmost element overwrites the left one.
a = {x: 1, y: 2};
b = {y: 3, z: 4};
result = {...b, ...a};
result2 = {...a, ...b};
console.log(result); // {x: 1, y: 2, z: 4}
console.log(result2); // {x: 1, y: 3, z: 4}
//if you don't want to create new object and just modify a then
Object.assign(a, {...b, ...a});
console.log(a); // {x: 1, y: 2, z: 4}
let a = { x: 1, y: 2 };
let temp = { ...a };
let b = { y: 3, z: 4 };
Object.assign(a, b);
Object.assign(a, temp);
console.log(a);
You could use Object.entries and filter out keys that are already in a.
eg.
a = {x: 1, y: 2}
b = {y: 3, z: 4}
//Object.assign(a, b)
// Now we get a = {x: 1, y: 3, z: 4}, so what if I want {x: 1, y: 2, z: 4}?
Object.assign(a, Object.fromEntries(
Object.entries(b).
filter(([k])=>!(k in a))));
console.log(a)
Finally I found the perfect solution is lodash.defaults.
https://lodash.com/docs/4.17.15#defaults
import _ from 'lodash'
a = {x: 1, y: 2}
b = {y: 3, z: 4}
_.defaults(a, b)
// Outputs {x:1, y:2, z:4}, perfectly as expected.
console.log(a)
Here's a simple piece of JavaScript where I want to add the contents of orders.foo and orders2.foo to a single-dimensional ordersArr.
let _ = require('underscore');
let ordersArr = [];
let orders = {
foo: [
{x: 1, b: 2},
{y: 1, c: 3},
{a: 2, d: 4}
]
}
ordersArr = _.map(orders.foo, order => order)
orders2 = {
foo: [
{x: 2, b: 3},
{y: 5, c: 4},
{a: 3, d: 6}
]
}
let tOrders = _.map(orders2.foo, order => order);
ordersArr.push(tOrders)
console.log(ordersArr);
The problem with this code is that push in this case creates a multi-dimensional array:
Output
[
{ x: 1, b: 2 },
{ y: 1, c: 3 },
{ a: 2, d: 4 },
[ { x: 2, b: 3 }, { y: 5, c: 4 }, { a: 3, d: 6 } ]
]
How do I iterate the contents of orders.foo and orders2.foo and have their results as one single dimension array?
You can spread the content of both arrays into the new array
const arr1 = [1,2,3];
const arr2 = [4,5,6];
const arr3 = [...arr1, ...arr2];
console.log(arr3);
// prints [1,2,3,4,5,6]
Spreading arr2 into arr1 also works.
arr1.push(...arr2);
console.log(arr1);
// prints [1,2,3,4,5,6]
So changing
ordersArr.push(tOrders)
to
ordersArr.push(...tOrders);
should work.
For a full answer:
let ordersArr = [];
let orders = {
foo: [
{x: 1, b: 2},
{y: 1, c: 3},
{a: 2, d: 4}
]
}
orders2 = {
foo: [
{x: 2, b: 3},
{y: 5, c: 4},
{a: 3, d: 6}
]
}
ordersArr.push(...orders.foo, ...orders2.foo);
Using underscore _.flatten:
const
orders = { foo: [ {x: 1, b: 2}, {y: 1, c: 3}, {a: 2, d: 4} ] },
orders2 = { foo: [ {x: 2, b: 3}, {y: 5, c: 4}, {a: 3, d: 6} ] };
const ordersArr = _.flatten([orders.foo, orders2.foo]);
console.log(ordersArr);
<script src="https://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.8.2/underscore-min.js"></script>
Using javascript spread operator:
const
orders = { foo: [ {x: 1, b: 2}, {y: 1, c: 3}, {a: 2, d: 4} ] },
orders2 = { foo: [ {x: 2, b: 3}, {y: 5, c: 4}, {a: 3, d: 6} ] };
const ordersArr = [...orders.foo, ...orders2.foo];
console.log(ordersArr);
Using javascript Array#concat:
const
orders = { foo: [ {x: 1, b: 2}, {y: 1, c: 3}, {a: 2, d: 4} ] },
orders2 = { foo: [ {x: 2, b: 3}, {y: 5, c: 4}, {a: 3, d: 6} ] };
const ordersArr = orders.foo.concat(orders2.foo);
console.log(ordersArr);
The spread operator mentioned above is the best 2021 way to do it.
let ordersArr = [...orders.foo, ...orders2.foo];
Use Array.concat()
let orders1 = {
foo: [
{x: 1, b: 2},
{y: 1, c: 3},
{a: 2, d: 4}
]
};
let orders2 = {
foo: [
{x: 2, b: 3},
{y: 5, c: 4},
{a: 3, d: 6}
]
};
console.log( orders1.foo.concat(orders2.foo) );
You can use concat() to merge the arrays and create a single new array:
let tOrders = orders.foo.concat(orders2.foo);
let ordersArr = [];
let orders = {
foo: [
{x: 1, b: 2},
{y: 1, c: 3},
{a: 2, d: 4}
]
}
ordersArr = _.map(orders.foo, order => order)
orders2 = {
foo: [
{x: 2, b: 3},
{y: 5, c: 4},
{a: 3, d: 6}
]
}
let tOrders = orders.foo.concat(orders2.foo);
console.log(tOrders)
<script src="https://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.8.2/underscore-min.js"></script>
Another option using flat()
let ordersArr = [];
let orders = {
foo: [
{x: 1, b: 2},
{y: 1, c: 3},
{a: 2, d: 4}
]
}
orders2 = {
foo: [
{x: 2, b: 3},
{y: 5, c: 4},
{a: 3, d: 6}
]
}
let tOrders = [orders.foo, orders2.foo].flat();
console.log(tOrders)
Immutable merge of arrays
Creates a new array.
Merge using the spread operator
let orders = {
foo: [
{x: 1, b: 2},
{y: 1, c: 3},
{a: 2, d: 4}
]
}
let orders2 = {
foo: [
{x: 2, b: 3},
{y: 5, c: 4},
{a: 3, d: 6}
]
}
const mergeResult = [...orders.foo, ...orders2.foo];
console.log(mergeResult);
Merge using array.concat() method
let orders = {
foo: [
{x: 1, b: 2},
{y: 1, c: 3},
{a: 2, d: 4}
]
}
let orders2 = {
foo: [
{x: 2, b: 3},
{y: 5, c: 4},
{a: 3, d: 6}
]
}
const mergeResult = orders.foo.concat(orders2.foo);
console.log(mergeResult);
Mutable merge of arrays
Merge it into existing array.
Merge using array.push() method
let orders = {
foo: [
{x: 1, b: 2},
{y: 1, c: 3},
{a: 2, d: 4}
]
}
let orders2 = {
foo: [
{x: 2, b: 3},
{y: 5, c: 4},
{a: 3, d: 6}
]
}
orders.foo.push(...orders2.foo);
console.log(orders.foo);
I'll add one more flavor to the list. You can create a shallow copy of an array using the built-in slice method, which has been with us for a very long time:
var ordersArr = orders.foo.slice();
Now you can add the contents of the other array using push and apply:
ordersArr.push.apply(ordersArr, orders2.foo);
Et voilá, ordersArr is now a one-dimensional array containing all elements of both orders.foo and orders2.foo. Works even in ES3!
For inspiration, you can find lots of nice little tricks like this in the Underscore source code.
i think this will work for you.
let tOrders = _.map(orders2.foo, order => order);
tOrders.foreach((element)=>{
ordersArr.push(element)
})
console.log(ordersArr);
var data = {
id: 1,
track: {
"1": [
{x: 10, y: 10},
{x: 11, y: 11},
{x: 12, y: 12}
],
"2": [
{x: 10, y: 10},
{x: 11, y: 11},
{x: 12, y: 12}
]
}
}
console.log(data.track);
var rev = data.track["1"].reverse();
console.log(rev);
How can i reverse every array inside "track" object? But I showed you above, that i am able to reverse array, by selecting it by key, but can i literally reverse every array inside "track" object?
Use Object.keys() to find all keys in your data structure
var data = {
id: 1,
track: {
"1": [
{x: 10, y: 10},
{x: 11, y: 11},
{x: 12, y: 12}
],
"2": [
{x: 10, y: 10},
{x: 11, y: 11},
{x: 12, y: 12}
]
}
}
var keys = Object.keys(data.track);
var count = keys.length;
for (var i=0;i<count;i++)
{
var rev = data.track[keys[i]].reverse();
console.log(rev);
}
It's simple. Just loop the data.track to get reverse result.
for (var i in data.track) {
console.log(data.track[i].reverse());
}
Consider the following code:
var input = [{x: 1, y: 6}, {x: 4, y: 3}, {x: 9, y: 2}];
var output = convert(input);
console.log(output); // = [1, 6, 4, 3, 9, 2]
What is the shortest, most concise convert function I can write that will give me the output shown?
So far I've come up with the following:
function convert(input) {
var output = [];
input.forEach(function(obj) {
output.push(obj.x, obj.y);
});
return output;
}
But surely there's a nice one-liner way of doing this?
With Array.prototype.reduce method it will save you two lines of code:
function convert(arr) {
return arr.reduce(function(prev, curr) {
return prev.concat(curr.x, curr.y);
}, []);
}
var input = [{x: 1, y: 6}, {x: 4, y: 3}, {x: 9, y: 2}];
document.write(JSON.stringify( convert(input) ));