Indent object values in an array of nested objects in JavaScript - javascript

I have an array like this :
[
{
name: 'foo',
nestedArray: [
{
name: 'bar',
nestedArray: []
}
]
}
]
What's the best way to have a flatten array that looks like this ?
[
{
name: 'foo',
nestedArray: [
{
name: 'bar',
nestedArray: []
}
]
},
{
name: ' bar',
nestedArray: []
}
]

You can try by iterating input array and moving out nested array objects into outer one. I hope this will work as per your expectation :
// Input array
const inputArray = [
{
name: 'foo',
nestedArray: [
{
name: 'bar',
nestedArray: []
}
]
}
];
// Result array
const res = [];
// Iterating input array and moving out nested array objects into outer one.
inputArray.forEach((obj) => {
res.push(obj);
obj.nestedArray.forEach((nestedObj) => {
res.push(nestedObj);
});
});
// Assigning result
console.log(res);

Related

Creating a nested object from array of keys and target values

I have and array of objects which I would like to transform into single js object.
The array contains target value and array of keys.
Note: I want this to work in vanilla js without importing scripts.
The source array:
[
{ value: 'res-1', keys: [ 'first' ] },
{ value: 'res-2', keys: [ 'second', 'deeperOne' ] },
{ value: 'res-3', keys: [ 'second', 'deeperTwo' ] },
{ value: 'res-4', keys: [ 'second', 'deeperThree', 'moreDeeper' ] },
{ value: 'res-5', keys: [ 'third' ]}
]
Desirable result (object):
{
first: 'res-1',
second: {
deeperOne: 'res-2',
deeperTwo: 'res-3',
deeperThree: {
moreDeeper: 'res-4'
}
},
third: 'res-5'
}
cmgchess gave answer to the question with a comment. Here is the code!
const array = [
{ value: 'res-1', keys: [ 'first' ] },
{ value: 'res-2', keys: [ 'second', 'deeperOne' ] },
{ value: 'res-3', keys: [ 'second', 'deeperTwo' ] },
{ value: 'res-4', keys: [ 'second', 'deeperThree', 'moreDeeper' ] },
{ value: 'res-5', keys: [ 'third' ]}
]
const set = (obj, path, value) => {
path.reduce((acc, key, i) => {
if (acc[key] === undefined) acc[key] = {}
if (i === path.length - 1) acc[key] = value
return acc[key]
}, obj)
}
let object = {}
array.forEach(({value, keys}) => set(object, keys, value))
console.log(object)

Dedupe and merge fields in a collection with Lodash (or vanilla JS)

I've been looking at this way too long and the answer's probably obvious, but I'm trying to combine a few arrays of objects.
Given 2 arrays of objects, I need to dedupe them based on the name field, but combine the actions array:
var map1 = [{
name: 'FOO',
actions: [{bar: 'bar1'}]
}, {
name: 'FOO2',
actions: [{bar: 'bar2'}]
}]
var map2 = [{
name: 'FOO',
actions: [{bar: 'bar3'}]
}]
The desired output would be:
[
{
name: 'FOO',
actions: [{bar: 'bar1'}, {bar: 'bar3'}] //merged by name "FOO"
},
{
name: 'FOO2',
actions: [{bar: 'bar2'}]
}
]
Here's a vanillaJS method. Note that your original objects had errors in their syntax which were corrected here.
You can use reduce to track the arrays by keys in order to be able to add to their action arrays using the [...] spread syntax. Because we want an array at the end, not an object, the whole result is passed through Object.values
let map1 = [{
name: 'FOO',
actions: [{
bar: 'bar1'
}]
}, {
name: 'FOO2',
actions: [{
bar: 'bar2'
}]
}]
let map2 = [{
name: 'FOO',
actions: [{
bar: 'bar3'
}]
}]
let result = Object.values([...map1, ...map2].reduce((b, a) => {
if (b.hasOwnProperty(a.name)) b[a.name].actions = [...b[a.name].actions, ...a.actions];
else b[a.name] = a;
return b;
}, {}))
console.log(result);

How to check if all objects of array are included another array?

I am trying to check if object array A includes objects from B.
let A = [
{ name: "Max" },
{ name: "Jhon" },
{ name: "Naton" },
]
let B = [
{ name: "Max" },
{ name: "Naton" },
]
So B has two objects that is in array A. How to check this ?
I am trying to achieve it with includes :
for(let entry of this.b){
if(this.a.includes(entry)){
console.log('includes');
}
}
But I get false on includes.
The method Array.includes() compare the entries of the array with the given value. Because your array entries are objects, it will not match. You have to loop at the array yourself and make the comparison.
Array.some() loops on an array and returns true if you returns true at least one. This method is useful when you want to verify something. In our example, we want to verify if the array a contains the b entry.
const a = [{
name: 'Max',
},
{
name: 'Jhon',
},
{
name: 'Naton',
},
];
const b = [{
name: 'Max',
},
{
name: 'Naton',
},
{
name: 'Daddy',
},
];
console.log(b.map(x => a.some(y => y.name === x.name)));
If I break it down :
const a = [{
name: 'Max',
},
{
name: 'Jhon',
},
{
name: 'Naton',
},
];
const b = [{
name: 'Max',
},
{
name: 'Naton',
},
{
name: 'Daddy',
},
];
// Loop on every entry of the b array
b.forEach((x) => {
// x here represent one entry
// first it will worth { name: 'Max' }, then { name: 'Naton' } ...
// for each value we are going to look at a if we can find a match
const isThereAMatch = a.some((y) => {
// y here is worth one entry of the a array
if (y.name === x.name) return true;
return false;
});
if (isThereAMatch === true) {
console.log(`We have found ${x.name} in a`);
} else {
console.log(`We have not found ${x.name} in a`);
}
});
You have to use another loop, then check the property name:
var a = [
{name: "Max"},
{name: "Jhon"},
{name: "Naton"},
];
var b = [
{name: "Max"},
{name: "Naton"},
];
for(let entry of b){
for(let entry2 of a){
if(entry2.name == entry.name){
console.log('includes', entry.name);
}
}
}
OR: You can use string version of object to check with includes():
var a = [
{name: "Max"},
{name: "Jhon"},
{name: "Naton"},
];
var b = [
{name: "Max"},
{name: "Naton"},
];
var aTemp = a.map(i => JSON.stringify(i));
var bTemp = b.map(i => JSON.stringify(i));
for(let entry of bTemp){
if(aTemp.includes(entry)){
console.log('includes', entry);
}
}
When you use Array#includes() method it will always return false because it's comparing objects which aren't equal because they aren't referencing the same object.
You should compare objects properties and not whole objects, you can do it using Array#some() method like this:
for (let entry of this.b) {
if (this.b.some(x => x.name === entry.name)) {
console.log('includes');
}
}
Demo:
A = [{
name: "Max"
},
{
name: "Jhon"
},
{
name: "Naton"
},
]
B = [{
name: "Max"
},
{
name: "Naton"
},
]
//Filter objects that exists in both arrays
let result = A.filter(el=> B.some(x => x.name === el.name));
console.log(result);

Best way to compare an array of strings to an array objects with string properties?

I have an array of object, within those objects is a name property.
const objArr = [ { name: "Avram" }, { name: "Andy" } ];
I’m collecting an array of strings from an outside source containing names.
const strArr = [ "Avram", "Andy", "Brandon" ];
If strArr contains a string that does not exist as a property name on an object in objArr, I need to create a new object and push it to objArr.
For example: objArr.push( { name: "Brandon" } );
Obviously, I can use nested loops, but I’d like to avoid that if possible. What is the best way to do this programmatically?
like this
const objArr = [ { name: "Avram" }, { name: "Andy" } ];
const strArr = [ "Avram", "Andy", "Brandon" ];
const names= objArr.map(x => x.name);
strArr.forEach(str => {
if (! names.includes(str) ) {
objArr.push({name: str});
}
});
console.log(objArr);
function fillMissing(arr, names) {
names.forEach(name => { // for each name in names
if(arr.every(obj => obj.name !== name)) { // if every object obj in the array arr has a name diferent than this name (this name doesn't exist in arr)
arr.push({name}); // then add an object with that name to arr
}
});
}
const objArr = [ { name: "Avram" }, { name: "Andy" } ];
const strArr = [ "Avram", "Andy", "Brandon" ];
fillMissing(objArr, strArr);
console.log(objArr);
Map objArr to same structure as strArr. Then concat the 2 arrays. Run it through a Set to remove duplicates, then remap to correct array of object
const objArr = [ { name: "Avram" }, { name: "Andy" }, { name: "John"} ];
const strArr = [ "Avram", "Andy", "Brandon" ];
const res = Array.from(new Set(objArr.map(i=>i.name).concat(strArr))).map(i=>({name:i}))
console.log(res);
const objArr = [ { name: "Avram" }, { name: "Andy" } ];
const strArr = [ "Avram", "Andy", "Brandon" ];
const objNamesArr = objArr.map((obj) => obj.name)
strArr.forEach((ele) => objNamesArr.indexOf(ele) == -1 && objArr.push({name:ele}))
console.log('objArr', objArr);
console.log('strArr', strArr);

How to get object that not match in another object lodash

I have 2 arrays with objects.
const a = [
{
name: 'John'
},
{
name: 'Adam'
}
]
const b = [
{
name: 'Adam'
}
]
I want to get the object is not the same in the array and also get the object that is same in arrays as well.
const same = [
{
name: 'Adam'
}
]
const not_same = [
{
name: 'John'
}
]
Using lodash library is it possible?
You can use intersectionBy and xorBy as follows:
const a = [{
name: 'John'
},
{
name: 'Adam'
}
];
const b = [{
name: 'Adam'
}];
console.log(_.intersectionBy(a, b, 'name')); // values present in both arrays
console.log(_.xorBy(a, b, 'name')); // values present in only one of the arrays
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.4/lodash.js"></script>
You can use _.partition() to get two arrays according to a certain criteria:
const a = [{
name: 'John'
},
{
name: 'Adam'
}
];
const b = [{
name: 'Adam'
}];
const bMap = _.keyBy(b, 'name'); // create a map of names in b
const [same, not_same] = _.partition(a, ({ name }) => name in bMap); // partition according to bMap and destructure into 2 arrays
console.log('same: ', same);
console.log('not_same: ', not_same);
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.4/lodash.min.js"></script>

Categories