How to flatten the nested Array? - javascript

How do I flatten the nested Array in the Array?
Here is the example input Array,
const input = [
{
id: 1,
name: 'Charles',
otherFields: [{
id: 2,
name: 'Pung',
}, {
id: 3,
name: 'James',
}]
}, {
id: 4,
name: 'Charles',
otherFields: [{
id: 5,
name: 'Pung',
}, {
id: 6,
name: 'James',
}]
}
]
Output Array I want to get.
[{
id: 1,
name: 'Charles'
}, {
id: 2,
name: 'Pung',
}, {
id: 3,
name: 'James',
}, {
id: 4,
name: 'Charles'
}, {
id: 5,
name: 'Pung',
}, {
id: 6,
name: 'James',
}]
I want to somehow get the output in one statement like
input.map((sth) => ({...sth??, sth.field...})); // I'm not sure :(

With flatMap you can take out the otherFields property, and returning an array containing the parent item and the other array:
const input = [{
id: 1,
name: 'Charles',
otherFields: [{
id: 2,
name: 'Pung',
}, {
id: 3,
name: 'James',
}]
}];
console.log(
input.flatMap(({ otherFields, ...item }) => [item, ...otherFields])
);

For more than one level, you could take a recursive approach of flattening.
const
flat = ({ otherFields = [], ...o }) => [o, ...otherFields.flatMap(flat)],
input = [{ id: 1, name: 'Charles', otherFields: [{ id: 2, name: 'Pung' }, { id: 3, name: 'James', otherFields: [{ id: 4, name: 'Jane' }] }] }],
result = input.flatMap(flat);
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }

Related

How can I get the result from arr1 and arr2, When the ID matches I need to copy the content from arr1

How can I get the result from arr1 and arr2, When the ID matches I need to copy the content from arr1
const arr1 = [
{ id: 1, name: "omar" },
{ id: 2, name: "laith" },
{ id: 3, name: "aref" },
]
const arr2 = [
{ id: 1, rating: "good" },
{ id: 2, rating: "very good" },
{ id: 2, rating: "very good" },
{ id: 3, rating: "Excellence" },
{ id: 3, rating: "Excellence" },
]
//expected output
const result = [
{ id: 1, rating: "good", name: "omar" },
{ id: 1, rating: "good", name: "omar" },
{ id: 2, rating: "very good", name: "laith" },
{ id: 3, rating: "Excellence", name: "aref" },
{ id: 3, rating: "Excellence", name: "aref" },
]
use reduce with filter
const arr1 = [ { id: 1, name: "omar" }, { id: 2, name: "laith" }, { id: 3, name: "aref" }, ];
const arr2 = [ { id: 1, rating: "good" }, { id: 2, rating: "very good" }, { id: 2, rating: "very good" }, { id: 3, rating: "Excellence" }, { id: 3, rating: "Excellence" }, ];
const result = arr1.reduce((acc,item) => {
const list = arr2.filter(i => i.id === item.id)
return [...acc, ...list.map(i => ({id: i.id,rating:i.rating, name: item.name}))]
}, [])
console.log(result)
Basically with a loop. Actually 2. Using a temporary object (result) as dictionary (or map) we can make it efficient searching for a match to each id. This is of complexity O(n) basically.
const arr1 = [ { id: 1, name: "omar" }, { id: 2, name: "laith" }, { id: 3, name: "aref" }, ];
const arr2 = [ { id: 1, rating: "good" }, { id: 2, rating: "very good" }, { id: 2, rating: "very good" }, { id: 3, rating: "Excellence" }, { id: 3, rating: "Excellence" }, ];
var result = {}
arr1.forEach(function(item1) {
result[item1.id] = item1;
});
arr2.forEach(function(item2) {
result[item2.id] = (result[item2.id] || item2)
result[item2.id]['rating'] = item2.rating
})
result = Object.values(result)
console.log(result)

How to get list of parents id in json object

My nested json array looks like:
[
{
id: 1,
name: "Mike",
children: [
{ id: 2, name: "MikeC1" },
{ id: 3, name: "MikeC2" },
{
id: 4, name: "MikeC3",
children: [{ id: 5, name: "MikeCC1" }]
},
]
},
{
id: 6,
name: "Json",
children: [
{ id: 7, name: "JsonC1" },
{ id: 8, name: "JsonC2" },
{
id: 9, name: "JsonC3",
children: [{ id: 10, name: "JsonCC1" },{ id: 11, name: "JsonCC2" }]
},
]
}
]
Now I get a id like "11"
then get the parent ids array in json like [6,9,11]
How to do?
var id = 11
console.log(findParent(id))
//result is [6,9,11]
You need to do recursive search
const persons = [
{
id: 1,
name: "Mike",
children: [
{ id: 2, name: "MikeC1" },
{ id: 3, name: "MikeC2" },
{
id: 4, name: "MikeC3",
children: [{ id: 5, name: "MikeCC1" }]
},
]
},
{
id: 6,
name: "Json",
children: [
{ id: 7, name: "JsonC1" },
{ id: 8, name: "JsonC2" },
{
id: 9, name: "JsonC3",
children: [{ id: 10, name: "JsonCC1" },{ id: 11, name: "JsonCC2" }]
},
]
}
];
function searchRecursive(items, id) {
const allIds = [];
items.forEach(item => {
if(item.id === id) {
allIds.push(item.id);
}
else if(item.children) {
const ids = searchRecursive(item.children, id);
if(ids.length) allIds.push(item.id);
ids.forEach(id => allIds.push(id));
}
});
return allIds;
}
console.log(searchRecursive(persons, 11));

Return a subarray with a value changed to reflect parent object

I am trying to change the value of single key in an associative array which is inside another assoc array using javascript.
I have an array like this:
let arr = [{
id: 4,
name: 'test',
docs: [{
id: 1,
name: 'abc'
},{
id: 2,
name: 'xyz'
}]
}, {
id: 8,
name: 'test2',
docs: [{
id: 5,
name: 'abc'
},{
id: 7,
name: 'xyz'
}]
}]
I want to change the value of name of xyz to xyz (test), where test is name key of parent object and get final array as Output:
[{
id: 1,
name: 'abc (test)'
},
{
id: 2,
name: 'xyz (test)'
},
{
id: 5,
name: 'abc (test2)'
},
{
id: 7,
name: 'xyz (test2)'
}]
I am using approach.
let docs = new Array();
arr.forEach((item, index) => {
let docx = item.documents.map(item1 => {
item1.name = item1.name + " ("+item.name+")";
});
docs.push(docx);
});
return docs;
this is returning array of undefined array.
Try a flatMap
let arr = [{ id: 4, name: 'test', docs: [{ id: 1, name: 'abc' },{ id: 2, name: 'xyz' }] }, { id: 8, name: 'test2', docs: [{ id: 5, name: 'abc' },{ id: 7, name: 'xyz' }] }]
const output = arr.flatMap(item =>
item.docs.map(({id,name}) => ({ id, name: `${name} (${item.name})` }))
)
console.log(output)
There is an issue in your data, the docs inner array contains an object with duplicate keys:
let arr = [{
id: 4,
name: 'test',
docs: [{
id: 1,
name: 'abc',
id: 2, // <-- duplicate key
name: 'xyz' // <-- duplicate key
}]
},
If I remove the duplication, you can use this code to create a new object with the name value updated to xyz123 if the original value was xyz:
const original = [{
id: 4,
name: 'test',
docs: [{
id: 1,
name: 'abc'
}, {
id: 2,
name: 'xyz'
}]
}, {
id: 8,
name: 'test2',
docs: [{
id: 1,
name: 'abc'
}, {
id: 2,
name: 'xyz'
}]
}];
const updates = original.map(currentObject => {
const newObject = Object.assign(currentObject);
const newDocs = newObject.docs.map(doc => {
const newDoc = Object.assign(doc);
if (newDoc.name === "xyz") {
newDoc.name = "xyz123";
}
return newDoc;
});
newObject.docs = newDocs;
return newObject
});
console.log(updates);

How to add object element in array based on condition

I have static array constant of objects something similar to below.
export const EMPLOYEES = [
{
id: 2,
name: ‘John’,
},
{
id: 3,
name: ‘Doe’,
},
{
id: 4,
name: ‘Bull’,
},
{
id: 5,
name: ‘Scott’,
},
];
Now I need to add the last element only based on if some condition is true. Some this like if isAmerican() is true.
Can somebody help me here how to add element based on the condition? Thanks.
You can do it using spread operator:
export const EMPLOYEES = [
{
id: 2,
name: "John",
},
{
id: 3,
name: "Doe",
},
{
id: 4,
name: "Bull",
},
{
id: 5,
name: "Scott",
},
... isAmerican() ? [{ id: 6, name: "Jemmy"}] : []
];
You should never modify (or try to modify) a constant. I can see two ways you can do this:
Create a pure function to return a new constant with the new object added to the array
Use a spread operator in the definition of the constant
Option 1: Pure function
function makeNewArray(array, objectToAppend, isAmerican) {
return isAmerican ? [...array, objectToAppend] : array
}
const EMPLOYEES = [
{
id: 2,
name: "John",
},
{
id: 3,
name: "Doe",
},
{
id: 4,
name: "Bull",
},
{
id: 5,
name: "Scott",
}
];
const arrayWithAmerican = makeNewArray(EMPLOYEES, { id: 6, name: "American Frank"}, true);
const arrayWithoutAmerican = makeNewArray(EMPLOYEES, { id: 6, name: "Not American Frank"}, false);
console.log(arrayWithAmerican);
console.log(arrayWithoutAmerican);
Option 2: Spread operator
function isAmerican(){
// generic code here.
return true;
}
const EMPLOYEES = [
{
id: 2,
name: "John",
},
{
id: 3,
name: "Doe",
},
{
id: 4,
name: "Bull",
},
{
id: 5,
name: "Scott",
},
... isAmerican() ? [{ id: 6, name: "American Frank"}] : []
];
If the condition will be fulfilled, simply push an object to your EMPLOYEES array:
let isAmerican = true;
const EMPLOYEES = [
{
id: 2,
name: "John",
},
{
id: 3,
name: "Doe",
},
{
id: 4,
name: "Bull",
},
{
id: 5,
name: "Scott",
},
];
if(isAmerican) {
EMPLOYEES.push({
id: 6,
name: "Frank"
})
}
console.log(EMPLOYEES)
Fiddle: https://jsfiddle.net/rqx35pLz/

How to unwind an Array of Objects in NodeJS?

I want to unwind an array of objects which have arrays of objects nested. The level of nesting is not defined and is not consistent throughout the array.
Here's my sample data
var data = [{
id: 1,
name: 'Harshal',
subjects: [{
id: 1,
name: 'English',
chapters: [{
id: 1,
name: 'Grammar'
}, {
id: 2,
name: 'Comprehension'
}]
}, {
id: 2,
name: 'Maths',
chapters: [{
id: 1,
name: 'Algebra'
}, {
id: 2,
name: 'Geometry'
}]
}]
}, {
id: 2,
name: 'Pankaj',
subjects: [{
id: 3,
name: 'Marathi',
chapters: [{
id: 1,
name: 'Kavita',
topics: [{
id: 1,
name: 'Topic 1'
}]
}]
}, {
id: 4,
name: 'Hindi',
chapters: [{
id: 1,
name: 'Katha',
topics: [{
id: 2,
name: 'Topic 2'
}, {
id: 3,
name: 'Topic 3'
}]
}]
}]
}];
I want to get an output like this:
var op = [{
id: 1,
name: 'Harshal',
subjects: {
id: 1,
name: 'English',
chapters: {
id: 1,
name: 'Grammar'
}
}
}, {
id: 1,
name: 'Harshal',
subjects: {
id: 1,
name: 'English',
chapters: {
id: 2,
name: 'Comprehension'
}
}
}, {
id: 1,
name: 'Harshal',
subjects: {
id: 2,
name: 'Maths',
chapters: {
id: 1,
name: 'Algebra'
}
}
}, {
id: 1,
name: 'Harshal',
subjects: {
id: 2,
name: 'Maths',
chapters: {
id: 2,
name: 'Geometry'
}
}
}, {
id: 2,
name: 'Pankaj',
subjects: {
id: 3,
name: 'Marathi',
chapters: {
id: 1,
name: 'Kavita',
topics: {
id: 1,
name: 'Topic 1'
}
}
}
}, {
id: 2,
name: 'Pankaj',
subjects: {
id: 4,
name: 'Hindi',
chapters: {
id: 1,
name: 'Katha',
topics: {
id: 2,
name: 'Topic 2'
}
}
}
}, {
id: 2,
name: 'Pankaj',
subjects: {
id: 4,
name: 'Hindi',
chapters: {
id: 1,
name: 'Katha',
topics: {
id: 3,
name: 'Topic 3'
}
}
}
}];
I have tried to work with pull-unwind but I guess there's some issues with it. If anyone has any other ideas, I'm open to implement those.
Have you tried recursion?
var data = [{
id: 1,
name: 'Harshal',
subjects: [{
id: 1,
name: 'English',
chapters: [{
id: 1,
name: 'Grammar'
}, {
id: 2,
name: 'Comprehension'
}]
}, {
id: 2,
name: 'Maths',
chapters: [{
id: 1,
name: 'Algebra'
}, {
id: 2,
name: 'Geometry'
}]
}]
}, {
id: 2,
name: 'Pankaj',
subjects: [{
id: 3,
name: 'Marathi',
chapters: [{
id: 1,
name: 'Kavita',
topics: [{
id: 1,
name: 'Topic 1'
}]
}]
}, {
id: 4,
name: 'Hindi',
chapters: [{
id: 1,
name: 'Katha',
topics: [{
id: 2,
name: 'Topic 2'
}, {
id: 3,
name: 'Topic 3'
}]
}]
}]
}];
function unravel(obj)
{
var out = [];
var added = false;
for(var i in obj) {
if(obj[i] instanceof Array) {
for(var j in obj[i]) {
var r = unravel(obj[i][j]);
for(var k in r) {
var a = {};
for(var key in obj) { // make copy of obj
a[key] = obj[key];
}
a[i] = r[k];
added = true;
out.push(a);
}
}
}
}
if(!added) {
out.push(obj);
}
return out;
}
var op = [];
for(var i in data)
op = op.concat(unravel(data[i]));
console.log(JSON.stringify(op, null, 4));

Categories

Resources