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

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);

Related

destructuring object into multiple object assignment

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.

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)

How would you check if property name(s) from one object exist in another?

I am trying to transfer/copy properties from object1 to object2, but only properties that are undefined in object2.
Thanks in advance, I hope this comes across clearly!
let object1 = { a: 1, b: 2, c: 3, d: 4 }
let object2 = { a: 'string' }
fillObj = function (object2, object1) {
for (let key in object1) {
if (typeof object2.key === undefined) {
object2[key] = object1[key];
}
}
return object2; //should return {a: 'string', b: 2, c: 3, d: 4 }
};
(1) Look properties on an object by a variable property name by using bracket notation, not dot notation
(2) To check if something is undefined, either compare against undefined directly, or use typeof and compare against the string 'undefined' (but this check isn't needed for this algorithm)
(3) Make sure the properties are own properties, not inherited properties, with hasOwnProperty
let object1 = { a: 'string' }
let object2 = { a: 1, b: 2, c: 3, d: 4 }
fillObj = function (object2, object1) {
for (let key in object1) {
if (object1.hasOwnProperty(key)) {
object2[key] = object1[key];
}
}
return object2; //should return {a: 'string', b: 2, c: 3, d: 4 }
};
console.log(fillObj(object2, object1));
Or use Object.entries, which iterates over own-properties only:
let object1 = { a: 'string' }
let object2 = { a: 1, b: 2, c: 3, d: 4 }
fillObj = function (object2, object1) {
for (const [key, val] of Object.entries(object1)) {
object2[key] = val;
}
return object2; //should return {a: 'string', b: 2, c: 3, d: 4 }
};
console.log(fillObj(object2, object1));

How to copy/overwrite an object using Object.assign() function?

How to fully copy / overwrite an object using Object.assign()?
If there would be another approach, it would be highly appreciated. :)
The purpose is to update the existing object to its new value.
Below is my code snippet and the expected result should be the same as the value of object2 only.
Expected result: { a: 8, b: 7 }
const object1 = {
a: 1,
b: 2,
c: {
d: 3
}
};
const object2 = {
a: 8,
b: 7
};
Object.assign(object1, object2);
console.log(object1);
For keeping the same object reference, you could remove all properties in advance and then assign the wanted properties with Object.assign.
const object1 = { a: 1, b: 2, c: { d: 3 } };
const object2 = { a: 8, b: 7 };
Object.assign(
Object.keys(object1).reduce((o, k) => (Reflect.deleteProperty(o, k), o), object1),
object2
);
console.log(object1);
IE
var object1 = { a: 1, b: 2, c: { d: 3 } },
object2 = { a: 8, b: 7 };
Object.keys(object2).reduce(
function (object, key) {
object[key] = object2[key];
return object;
},
Object.keys(object1).reduce(function (object, key) {
delete object[key];
return object;
}, object1)
);
console.log(object1);
If you want to override the object1 properties with those from object2, you need to do it like this:
object1 = Object.assign({}, object2);
But with this you need to declare object1 with var keyword so you can assign a new value to it.
Demo:
var object1 = {
a: 1,
b: 2,
c: {
d: 3
}
};
const object2 = {
a: 8,
b: 7
};
object1 = Object.assign({}, object2);
console.log(object1);

How can I uniquely union two array of objects?

I am trying to merge two arrays of objects without using the unionBy method from lodash.
Currently I have the following code working perfectly:
var array1 = [
{ a: 1, b: 'first'},
{ a: 2, b: 'second'}
];
var array2 = [
{ a: 3, b: 'third'},
{ a: 1, b: 'fourth'}
];
var array3 = __.unionBy(array2, array1, 'a');
This outputs:
[
{
"a": 3,
"b": "third"
},
{
"a": 1,
"b": "fourth"
},
{
"a": 2,
"b": "second"
}
]
This is the desired result but I can't use unionBy in my current work environment, so I'm looking for a result that uses either native JS or other lodash methods 3.6.0 or lower.
Concat and use Array#filter with a helper object to remove duplicates:
var array1 = [{"a":1,"b":"first"},{"a":2,"b":"second"}];
var array2 = [{"a":3,"b":"third"},{"a":1,"b":"fourth"}];
var result = array2.concat(array1).filter(function(o) {
return this[o.a] ? false : this[o.a] = true;
}, {});
console.log(result);
If ES6 is an option you can use a Set instead of the helper object:
const array1 = [{"a":1,"b":"first"},{"a":2,"b":"second"}];
const array2 = [{"a":3,"b":"third"},{"a":1,"b":"fourth"}];
const result = array2.concat(array1).filter(function(o) {
return this.has(o.a) ? false : this.add(o.a);
}, new Set());
console.log(result);
If you want to use an arrow function, you can't use the thisArg of Array.filter() to bind the Set as the this of the function (you can't bind this to arrow functions). You can use a closure instead (attribute for the method goes to #NinaScholz).
const array1 = [{"a":1,"b":"first"},{"a":2,"b":"second"}];
const array2 = [{"a":3,"b":"third"},{"a":1,"b":"fourth"}];
const result = [...array2, ...array1]
.filter((set => // store the set and return the actual callback
o => set.has(o.a) ? false : set.add(o.a)
)(new Set()) // use an IIFE to create a Set and store it set
);
console.log(result);
You could take a Set for filtering to get unique values.
var array1 = [{ a: 1, b: 'first' }, { a: 2, b: 'second' }],
array2 = [{ a: 3, b: 'third' }, { a: 1, b: 'fourth' }],
s = new Set,
array3 = array2.map(o => (s.add(o.a), o)).concat(array1.filter(o => !s.has(o.a)));
console.log(array3);
You can use an ES6 Map for this. Construct it with the data, keyed by the a property value, and then take the values out of the Map again:
var array1 = [{"a":1,"b":"first"},{"a":2,"b":"second"}],
array2 = [{"a":3,"b":"third"},{"a":1,"b":"fourth"}];
var result = [...new Map([...array1,...array2].map( o => [o.a, o] )).values()];
console.log(result);
You can merge the 2 arrays and then filter the ones with same property a:
var array1 = [{ a: 1, b: 'first'},{ a: 2, b: 'second'}],
array2 = [{ a: 3, b: 'third'},{ a: 1, b: 'fourth'}],
array3 = [...array2, ...array1].filter((item, pos, arr) =>
arr.findIndex(item2 => item.a == item2.a) == pos);
console.log(array3)
If you want to still be able to specify the property by which to union you can implement you own function like this:
var array1 = [{ a: 1, b: 'first'},{ a: 2, b: 'second'}],
array2 = [{ a: 3, b: 'third'},{ a: 1, b: 'fourth'}],
array3 = unionBy(array1, array2, 'a');
function unionBy(array1, array2, prop){
return [...array2, ...array1].filter((item, pos, arr) =>
arr.findIndex(item2 => item[prop] == item2[prop]) == pos);
}
console.log(array3);
Note: One advantage of my answer over some of the answers is that it preserves the order like in lodash which may or may not be important.
ES5 using Array.filter and Array.find
var array1 = [{ a: 1, b: "first" }, { a: 2, b: "second" }];
var array2 = [{ a: 3, b: "third" }, { a: 1, b: "fourth" }];
function merge(a, b, prop) {
var reduced = a.filter(function(itemA) {
return !b.find(function(itemB) {
return itemA[prop] === itemB[prop];
});
});
return reduced.concat(b);
}
console.log(merge(array1, array2, "a"));
ES6 arrow functions
var array1 = [{ a: 1, b: "first" }, { a: 2, b: "second" }];
var array2 = [{ a: 3, b: "third" }, { a: 1, b: "fourth" }];
function merge(a, b, prop) {
const reduced = a.filter(
itemA => !b.find(itemB => itemA[prop] === itemB[prop])
);
return reduced.concat(b);
}
console.log(merge(array1, array2, "a"));
Another ES6 one line experiment
var array1 = [{ a: 1, b: "first" }, { a: 2, b: "second" }];
var array2 = [{ a: 3, b: "third" }, { a: 1, b: "fourth" }];
const merge = (a, b, p) => a.filter( aa => ! b.find ( bb => aa[p] === bb[p]) ).concat(b);
console.log(merge(array1, array2, "a"));
You could use ES6 find and reduce function smartly!
var array1 = [{"a":1,"b":"first"},{"a":2,"b":"second"}];
var array2 = [{"a":3,"b":"third"},{"a":1,"b":"fourth"}];
var res = array1.concat(array2).reduce((aggr, el)=>{
if(!aggr.find(inst=>inst.a==el.a))
return [...aggr, el];
else
return aggr
},[])
console.log(res);

Categories