This question already has answers here:
Update javascript object with another object, but only existing keys
(6 answers)
Closed 10 months ago.
How to achive this result :
const defaultValues = { a:1, b:1 , c:1};// All acceptable properties
const overrideValues = { a:2, x: 3, y: 3, z:3 };// from user
const values = ? ;//
console.log(values);
// output:
// Object { a: 2, b: 1, c: 1 }
Thxs,
Post-Edit :
Thank you all for your precious help.
(I read the duplicate question: Update javascript object with another object, but only existing keys)
However, I still offer you my solution :
const overrideValues = { a:2, x: 3, y: 3, z:3 };
const defaultValues = {
a: overrideValues.a || 1,
b: overrideValues.b || 1,
c: overrideValues.c || 1
};
const values = defaultValues ;// !
console.log(values);
// output:
// Object { a: 2, b: 1, c: 1 }
You can map over the entries of the default values and set the value to the value in overrideValues for each key that exists on that object.
const defaultValues = { a:1, b:1 , c:1};
const overrideValues = { a:2, x: 3, y: 3, z:3 };
const values = Object.fromEntries(Object.entries(defaultValues)
.map(([k,v])=>[k, overrideValues.hasOwnProperty(k) ? overrideValues[k] : v]));
console.log(values);
You can use spread syntax:
const defaultValues = { a:1, b:1 , c:1};// All acceptable values
const overrideValues = { a:2, x: 3, y: 3, z:3 };
const values = {...defaultValues, ...overrideValues};
console.log(values);
Spread syntax allows you to destructure an object or array, and you can use that restructuring to have default values. If there are multiple instances of a key/value pair, then the second value seen for that key is used, allowing you to override the defaults.
Related
This question already has answers here:
Clean way to keep original variable and destructure at the same time
(5 answers)
Closed 2 years ago.
I have an object. I know I can destructure to retrieve the value of any entry, and use spread operator to retrieve the rest of them
const [a, ...rest] = [1, 2, 3];
console.log(a); // 1
console.log(rest); // [ 2, 3 ]
I would like to know if there is any sintaxis to retrieve both a value of any entry, and the object itself redeclared to a new var, something like the following —although I know is wrong—:
const [a], myArrayInANewVar = [1, 2, 3];
console.log(a); // 1
console.log(myArrayInANewVar); // [ 1, 2, 3 ]
Thanks in advance!
Why not take two assignments?
const myObject = {
a: 1,
b: 2,
};
const
{ a } = myObject,
{ ...copy } = myObject;
console.log(a);
console.log(copy);
A chained assignemnt does not work because the nested variables are created outside of the actual scope.
function ownScope() {
const
myObject = { a: 1, b: 2, },
{ a } = { ...copy } = myObject;
console.log(a);
console.log(copy);
}
ownScope();
console.log(copy); // global
const [a] = (myArrayInANewVar = [1, 2, 3]);
console.log(a); // 1
console.log(myArrayInANewVar); // [ 1, 2, 3 ]
I have two immutable map:
const first_map = Map({a: 1, b: 2)}
const second_map = Map({a: 1, b: 3)}
How to get the difference?
I should get:
Map({b: 3})
One possible approach is using Map.filter() - which is actually Collection.Keyed.filter() - on the second map with one condition: for a given element of this Map, there should be no element in another Map with the same key. For example:
const Map = Immutable.Map;
const first_map = Map({a: 1, b: 2, c: 4});
const second_map = Map({a: 1, b: 3, d: 5});
const diff = second_map.filter((v, k) => first_map.get(k) !== v);
console.log(diff.toString()); // Map { "b": 3, "d": 5 }
<script src="https://cdnjs.cloudflare.com/ajax/libs/immutable/3.8.2/immutable.min.js"></script>
Strictly speaking, one should check for has first - as Map.get(key) returns undefined if there's no such key, but there might be valid cases for Map containing undefined. Still, I'd encourage using null for such values.
This question already has answers here:
How to deep merge instead of shallow merge?
(47 answers)
Closed 2 years ago.
I have a nested default object that I want to both extend and overwrite with nested properties. I tried with the spread operator but you can also use Ojbect.assign.
The problem is that nested objects get overridden instead of their respective properties getting overridden and/or extended.
const defaultOptions = {
a: 0,
b: 1,
c: {
hello: 'world',
age: 20
}
};
const specialOptions = {
b: 0,
c: {
age: 10
},
d: 1
};
const options = {
...defaultOptions,
...specialOptions
}
console.log(options)
const expectedOptions = {
a: 0,
b: 0,
c: {
hello: 'world',
age: 10
},
d: 1
}
console.log(expectedOptions)
Update 2021-08-24
It seems this question is a duplicate of another so therefore I will delete it.
Here is a recursive solution, although it mutates the input object and doesn't return a new one, as I would've wanted. Hence why I added the deepCopy function.
Also, the order isn't maintained. But I assume that isn't of the biggest concern if you are using objects in the first place.
const defaultOptions = {
a: 0,
b: 1,
c: {
hello: 'world',
age: 20
}
}
const specialOptions = {
b: 0,
c: {
age: 10
},
d: 1
}
const deepCopy = obj => JSON.parse(JSON.stringify(obj))
const options = deepCopy(specialOptions)
const extendObj = (defaults, obj) => {
Object.entries(defaults)
.forEach(([key, value]) => {
if (obj[key] === undefined) {
obj[key] = value
} else if (typeof value === 'object') {
extendObj(defaults[key], obj[key])
}
})
}
extendObj(defaultOptions, options)
console.log(options)
This question already has answers here:
Javascript | Unique object in Set
(2 answers)
Closed 4 years ago.
I have a logic that accepts a configuration and returns a value. However, I'd like to retrieve from the cache for the further tries of same configuration. The order of keys may be varied within the config but must be treated as the same configuration.
Comments explain what I try to achieve. I expect only two openings as there are only two different config in the sample code. Only first and second attempts of open() goes as expected because of the same object passing to the map as a key.
If I try to keep the keys as a JSON string then the order of the keys can be problematic.
Here is what I have tried so far. I appreciate any idea or alternative solution.
var m = new Map();
function opening(config) {
// ...
return "foo";
}
function open(config = {}) {
if (!m.has(config)) {
m.set(config, opening(config));
console.log("open and set: ", config);
} else {
console.log("get from the map: ", config);
}
return m.get(config);
}
var c1 = { a: 1, b: 2 };
open(c1); // open and set [OK]
open(c1); // get from the map [OK]
open({ a: 1, b: 2 }); // get from the map
open({ b: 2, a: 1 }); // get from the map, even in different orders
open({ a: 1, b: 2, c: 3 }); // open and set
open({ a: 1, c: 3, b: 2 }); // get from the map
It looks like you need a way to represent the different objects such that identical key-value pairs (in different orders) can be recognized as the same key in the map. One option would be to take the object and sort its entries according to the keys' alphabetical order, and then stringify the sorted entries:
var m = new Map();
function opening(config) {
// ...
return "foo";
}
function open(config = {}) {
const key = objToKeyValStr(config);
if (!m.has(key)) {
m.set(key, opening(config));
console.log("open and set: ", config);
} else {
console.log("get from the map: ", config);
}
return m.get(config);
}
function replacer(_, value) {
if (typeof value !== 'object' || Array.isArray(value)) return value;
return objToKeyValStr(value);
}
const objToKeyValStr = obj => (
JSON.stringify(
Object.entries(obj).sort((a, b) => a[0].localeCompare(b[0])),
replacer
)
);
var c1 = { a: 1, b: 2 };
open(c1); // open and set [OK]
open(c1); // get from the map [OK]
open({ a: 1, b: 2 }); // get from the map
open({ b: 2, a: 1 }); // get from the map, even in different orders
open({ a: 1, b: 2, c: 3 }); // open and set
open({ a: 1, c: 3, b: 2 }); // get from the map
open({ a: 1, b: { c: 1, d: 1 }}); // open and set
open({ a: 1, b: { d: 1, c: 1 }}); // get from the map
I'm trying to convert an object which contains arrays as its property, to an array which contains all elements from these nested arrays.
Here's what i am trying to do:
data1 = [{
a: 1,
b: ["uz", "vy"]
}, {
a: 2,
b: ["wxa", "xwy"]
}, {
a: 6,
b: ["ysa", "zaa"]
}]
data1.reduce(function(q, w) {
return q.b.concat(w.b)
})
I want the final data to look like this:
data1 = ["uz","vy","wxa","xwy","ysa","zaa"]
However this gives an error message :
"Uncaught TypeError: Cannot read property 'concat' of undefined"
If q.b refers to array inside object, why does it not have concat property?
What am i doing wrong here?
You are getting an error because q is an array and not an object with b property. And you did not add the initial value.
You can concat and map
let data1 = [{a: 1,b: ["uz", "vy"]}, {a: 2,b: ["wxa", "xwy"]}, {a: 6,b: ["ysa", "zaa"]}];
let result = [].concat(...data1.map(o => o.b));
console.log(result);
If you want to use reduce, you can:
let data1 = [{a: 1,b: ["uz", "vy"]}, {a: 2,b: ["wxa", "xwy"]}, {a: 6,b: ["ysa", "zaa"]}];
let result = data1.reduce(function(q, w) {
return q.concat(w.b);
}, []); //<-- Add [] to initiate the initial value
console.log(result);
Pass an initial value to the reduce function. Also, q.b will not be a valid value in the first call. You wanted to concat to q instead:
data1 = [{
a: 1,
b: ["uz", "vy"]
}, {
a: 2,
b: ["wxa", "xwy"]
}, {
a: 6,
b: ["ysa", "zaa"]
}]
var result = data1.reduce(function(q, w) {
return q.concat(w.b);
}, [])
console.log(result);