destructuring object into multiple object assignment - javascript

I have an object like so:
const obj = {
a: 1,
b: 2,
c: 3,
d: 4,
e: 5
}
I want to create multiple object literals out of it. So:
const obj1 = {
a: 1,
b: 2
}
const obj2 = {
c: 3,
d: 4,
e: 5
}
Is it possible to achieve this using an object destructing assignment?
Something like:
const { {a, b}: obj1, {c, d, e}: obj2} = obj;

Is it possible to achieve this using object destructuring assignment?
No, it is not possible. However, you can write a function to split an object by its property names into multiple objects like this:
function splitObject (obj, ...propertyGroups) {
return propertyGroups.map(group => {
const o = {};
for (const key of group) o[key] = obj[key];
return o;
});
}
const obj = {
a: 1,
b: 2,
c: 3,
d: 4,
e: 5,
};
const [obj1, obj2] = splitObject(obj, ['a', 'b'], ['c', 'd', 'e']);
console.log({obj, obj1, obj2});
By returning the sub-objects in a tuple, you have the freedom to destructure it, naming each one according to your preference.

Related

Adding keys in one JavaScript Object to another only if the first object doesn't have those keys

function extend(obj1, obj2) {
var obj2Keys = Object.keys(obj2);
var obj2Values = Object.values(obj2);
var obj1Keys = Object.keys(obj1);
var obj1Values = Object.keys(obj1);
var newObj = {};
for(var i=0; i<obj1Keys.length; i++) {
if(obj1Keys[i] !== obj2Keys[i]) {
}
}
}
var obj1 = {
a: 1,
b: 2
};
var obj2 = {
b: 4,
c: 3
};
extend(obj1, obj2);
console.log(obj1); // --> {a: 1, b: 2, c: 3}
console.log(obj2); // --> {b: 4, c: 3}
/*
1. Add any keys that are not in the 1st object.
2. If the 1st object already has a given key, ignore it (do not
overwrite the property value).
3. Do not modify the 2nd object at all.
*/
Hey guys, trying to figure this one out. I'm sure i'm doing this the most inefficient way. I'm struggling to compare indexes of these objects.. Any help?? I was using for in loops originally but I couldn't conceptually understand what I was doing lol. Kinda stuck at this point.
const firstObject = {a:1,b:2,c:3}
const secondObject = {a:11,b:22,c:33,d:44}
var newObject = {...secondObject,...firstObject}
console.log(newObject)
result:
{"a":1,"b":2,"c":3,"d":44}
Get keys of obj2
Iterate over them using the for-loop
In each iteration, if obj1 does not have this key, and the record to it from obj2
function extend (obj1, obj2) {
const obj2Keys = Object.keys(obj2);
for(let i = 0; i < obj2Keys.length; i++) {
const currentKey = obj2Keys[i]
if(!obj1[currentKey]) {
obj1[currentKey] = obj2[currentKey];
}
}
}
const obj1 = { a: 1, b: 2 }; const obj2 = { b: 4, c: 3 };
extend(obj1, obj2);
console.log(obj1); // --> {a: 1, b: 2, c: 3}
console.log(obj2); // --> {b: 4, c: 3}
Another way using .forEach:
function extend (obj1, obj2) {
Object.keys(obj2).forEach(currentKey => {
if(!obj1[currentKey]) {
obj1[currentKey] = obj2[currentKey];
}
});
}
const obj1 = { a: 1, b: 2 }; const obj2 = { b: 4, c: 3 };
extend(obj1, obj2);
console.log(obj1); // --> {a: 1, b: 2, c: 3}
console.log(obj2); // --> {b: 4, c: 3}
Use the spread syntax to combine the objects. The spread syntax basically inserts the objects key/value pairs wherever you write it, so you're creating a new object with {...obj1, ...obj2}. If there are pairs with duplicate keys, the pair from the second object will be selected.
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Spread_syntax
let obj1 = {a: 1, b: 2}
let obj2 = {b: 4, c: 3}
let obj3 = {...obj2, ...obj1}
console.log(obj3)

If object has specific properties create a new object only with them

As always I will explain my problem by example (that I solved but its a lot of code and its ugly, that's why I'm looking for a better solution). I'm trying to look at an object like this:
const object1 = {
a: {a:1},
b: 2,
c: 3,
d: 4,
};
I want to check if this object has any of the following properties [a,f] and if have one of them to create a new object with these properties
const object2 = {
a: {a:1},
};
const object1 = {
a: {a:1},
b: 2,
c: 3,
d: 4,
}
const arrOfItem = ['a', 'd']
const newObj = {}
for(let item in object1) {
if(arrOfItem.includes(item)) {
newObj[item]= object1[item]
}
}
console.log(newObj)
see if this works for you,
function makeObject (properties) {
const originalObject = {
a: {a:1},
b: 2,
c: 3,
d: 4,
};
let newObject = {}
properties.forEach(property => {
if(originalObject.hasOwnProperty(property)) {
newObject[property] = originalObject[property];
}
});
return newObject;
}
pass the properties as an array of strings to makeObject function
const d = ['a', 'f', 'd']
const object1 = {
a: {a:1},
b: 2,
c: 3,
d: 4,
};
const object2 = d.reduce((acc, ele) => {
if(object1[ele] !== undefined) acc[ele] = object1[ele];
return acc;
}, {});
console.log(object2);

Access a property on an object from an array of keys

I want to write a helper function to unpack a specific object property from each object in an array of objects. Sometimes this property will be top level, other times it will be nested an arbitrary number of levels. So the crux of this question is: how can I access an object property based on an array of key names of variable length?
I'm hoping for something like:
const func = (arrOfObjects, ...keys) {
return arrOfObjects.map(object => {
return object[keys[0]][keys[1]] ... [keys[N]];
})
}
with example behaviour:
const input = [
{a: b: {c: 10}},
{a: b: {c: 11}},
{a: b: {c: 12}}
]
console.log(func(input, 'a', 'b', 'c'))
// [10, 11, 12]
console.log(func(input, 'a', 'b'))
// [{c: 10}, {c: 11}, {c : 12}]
I feel like there has to be a nice ES6 wizardry solution but as yet haven't found it so any help would be much appreciated!
Cheers,
P
You can get a short and easy solution using Array#reduce
const input = [
{a: { b: {c: 10}}},
{a: { b: {c: 11}}},
{a: { b: {c: 12}}}
]
console.log(func(input, ['a', 'b', 'c']))
// [10, 11, 12]
console.log(func(input, ['a', 'b']))
// [{c: 10}, {c: 11}, {c : 12}]
function func(input, props) {
return input.map(x => exctractByProps(x, props));
}
function exctractByProps(obj, props) {
return props.reduce(
(acc, prop) => typeof acc === 'object' && prop in acc ? acc[prop] : undefined,
obj
)
}
The main logic is to grab all the properties passed in and then try to get the value corresponding to obj[prop[0]][prop[1]][prop[2]]/* ... */[prop[n]]. If the object has an odd shape that doesn't match up with prop (for example, an input of {a: 1}, ['a', 'b'] or {d: {c: 1}}, ['a', 'b']) then the function returns undefined.
Based on the answers you gave me to my questions and your example. It seems as if the order will of the input will always match the objects nesting. So here is my solution:
const func = (arrOfObjects, ...keys) => {
return arrOfObjects.map(object => {
let obj = object, integer = keys.length;
for (let index = 0; index < integer; index++) {
obj = obj[keys[index]];
if(obj === undefined) break;
}
return obj;
});
};
const input = [
{ a: { b: { c: 10 } } },
{ a: { b: { c: 11 } } },
{ a: { b: { c: 12 } } }
];
console.log(func(input, "a", "b", "c"));
// [10, 11, 12]
console.log(func(input, "a", "b"));
// [{c: 10}, {c: 11}, {c : 12}]
Unfortunately there is no such thing as the javascript magic you where expecting.
Note: this code will not work when the order of the keys inside the object are nested at random depth. But for what you are trying to solve, this should work just fine. Also, I tried to preserve your initial code as good as possible
If you supply the accessor like [a, b, c[0], name], you can write a custom function which returns the value if found in a nested Object, otherwise returns undefined
let obj = {
a: 1,
b: 2,
c: {
d: 1,
e: [{
f: 3,
g: [{
z: 45
}]
}]
}
}
function findKeyFromPattern(obj, patternArr) {
let value = obj;
for(let i = 0; i < patternArr.length; i++) {
const arrmatch = patternArr[i].match(/(\w+)\[(\d+)\]/);
if(arrmatch) { // pattern matches and array accessor syntax
value = value[arrmatch[1]];
if(typeof value === 'object' && value !== null) {
value = value[arrmatch[2]];
} else {
return;
}
} else {
if(value[patternArr[i]]) {
value = value[patternArr[i]];
} else {
return;
}
}
}
return value;
}
console.log(findKeyFromPattern(obj, ['c', 'e[0]', 'g']));
console.log(findKeyFromPattern(obj, ['c', 'e[1]', 'g']))

Does an ES6 shorthand exist for copying a subset of an object's properties into a new object? [duplicate]

This question already has answers here:
One-liner to take some properties from object in ES 6
(12 answers)
How to get a subset of a javascript object's properties
(36 answers)
Closed 6 years ago.
Consider the following object:
const obj = {a: 1, b: 2, c: 3, d: 4, e: 5}
Is there a simple syntax for creating a new object that contains:
const obj2 = {a, b, d}
I'm aware that underscore & lodash have .pick(), but I'm hoping there's some kind of destructuring trickery that I may not be aware of.
Concise one-liner in ES2015 is
const obj2 = (({a, b, d}) => ({a, b, d}))(obj);
It doesn't seem to be possible to avoid {a, b, d} tautology while keeping it compact at the same time.
You can do it in two steps:
const obj = {a: 1, b: 2, c: 3, d: 4, e: 5};
var {a, b, d} = obj;
const obj2 = {a, b, d};
If you don't want to pollute the scope,
const obj = {a: 1, b: 2, c: 3, d: 4, e: 5};
const obj2 = {};
{
let {a, b, d} = obj;
Object.assign(obj2, {a, b, d});
}
You could use Rest parameters and create custom pick function like this
const obj = {a: 1, b: 2, c: 3, d: 4, e: 5}
function pick(object, ...p) {
return p.reduce((o, e) => {return o[e] = object[e], o}, {});
}
console.log(pick(obj, 'a', 'b', 'd'))

Filtering an object by property in Ramda.js

I'm new to using Ramda.js and am wondering how I can filter an object based on specified properties.
Looking at R.filter, it seems that _.filter only passes the object value and not the property. For instance, the example given in the REPL:
var isEven = (n, prop) => {
console.log(typeof prop);
// =>
// undefined
// undefined
// undefined
// undefined
return n % 2 === 0;
}
R.filter(isEven, {a: 1, b: 2, c: 3, d: 4}); //=> {b: 2, d: 4}
If I have the following object:
const obj = {a: 1, b: 2, c: 3};
My desired result would be:
const filterProp = (x) => /* some filter fn */;
filterProp('b')(obj);
// => {a: 1, c: 3};
How can I use Ramda to filter the properties of an object?
After digging through the Ramda docs, I found R.omit which satisfies my particular use case.
const obj = {a: 1, b: 2, c: 3};
R.omit(['b'], obj);
// => {a: 1, c: 3};
Use the pickBy method which allows you to filter a collection based on the keys.
const obj = {a: 1, b: 2, c: 3};
var predicate = (val, key) => key !== 'b';
R.pickBy(predicate, obj);
// => {a: 1, c: 3}

Categories