Access nested array of objects - javascript

im having real trouble to complete an FullStackOpen exersice, it requires to render some data to the page. Give the next code, i have to render the number of Parts that each Course has, and also so reduce the number of Parts/Exersices to render the total of exersices por each Course.
I am not being able to reach the inside of the Parts array of objects
{
name: "Half Stack application development",
id: 1,
parts: [
{
name: "Fundamentals of React",
exercises: 10,
id: 1,
},
{
name: "Using props to pass data",
exercises: 7,
id: 2,
},
{
name: "State of a component",
exercises: 14,
id: 3,
},
{
name: "Redux",
exercises: 11,
id: 4,
},
],
},
{
name: "Node.js",
id: 2,
parts: [
{
name: "Routing",
exercises: 3,
id: 1,
},
{
name: "Middlewares",
exercises: 7,
id: 2,
},
],
},
];```

It's not that difficult, for each element of the array:
number of parts is currentElement.parts.length
number of exercises can be computed using Array.reduce
const data = [
{
name: "Half Stack application development",
id: 1,
parts: [{
name: "Fundamentals of React",
exercises: 10,
id: 1,
},
{
name: "Using props to pass data",
exercises: 7,
id: 2,
},
{
name: "State of a component",
exercises: 14,
id: 3,
},
{
name: "Redux",
exercises: 11,
id: 4,
},
],
},
{
name: "Node.js",
id: 2,
parts: [{
name: "Routing",
exercises: 3,
id: 1,
},
{
name: "Middlewares",
exercises: 7,
id: 2,
},
],
},
];
const res = []
for (const course of data) {
const tmpObj = {
courseName: course.name,
parts: course.parts.length,
exercises: course.parts.reduce((a,b) => a + b.exercises, 0)
}
res.push(tmpObj)
}
console.log(res)

If you want a total number of exercises per course, you will need to reduce each by name; and for each list of parts, reduce by the exercise count.
const main = () => {
const courseData = courses.map(({ name, parts }) => ({
name,
parts: parts.length,
exercises: parts.reduce((sum, { exercises }) => sum + exercises, 0)
}));
console.log(courseData);
};
const courses = [{
name: "Half Stack application development",
id: 1,
parts: [
{ name: "Fundamentals of React" , exercises: 10 , id: 1 },
{ name: "Using props to pass data" , exercises: 7 , id: 2 },
{ name: "State of a component" , exercises: 14 , id: 3 },
{ name: "Redux" , exercises: 11 , id: 4 }
],
}, {
name: "Node.js",
id: 2,
parts: [
{ name: "Routing" , exercises: 3 , id: 1 },
{ name: "Middlewares" , exercises: 7 , id: 2 }
],
}];
main();
.as-console-wrapper { top: 0; max-height: 100% !important; }

Related

How to get values of child objects in an array of objects in javascript

states = [{
name: telangana,
cities: [{
id: 1,
name: foo
}, {
id: 2,
name: joo
}, {
id: 3,
name: goo
}]
},
{
name: punjab,
cities: [{
id: 4,
name: tyu
}, {
id: 5,
name: ery
}, {
id: 6,
name: doo
}]
},
{
name: mumbai,
cities: [{
id: 7,
name: eee
}, {
id: 8,
name: qqq
}, {
id: 9,
name: www
}]
},
]
I want response like [foo, joo, goo, tyu, ery,doo, eee,qqq,www]
Can someone help me ?
Just write one line:
Learn more about reduce() and map()
const states = [{ name: "telangana", cities: [{ id: 1, name: "foo" }, { id: 2, name: "joo" }, { id: 3, name: "goo" }] }, { name: "punjab", cities: [{ id: 4, name: "tyu" }, { id: 5, name: "ery" }, { id: 6, name: "doo" }] }, { name: "mumbai", cities: [{ id: 7, name: "eee" }, { id: 8, name: "qqq" }, { id: 9, name: "www" }] }, ];
const result = states.reduce((acc, { cities }) => [...acc, ...cities.map(({ name }) => name)], []);
console.log(result);
const getNames = (data) => {
const nameArr = [];
data.forEach((ele) => {
ele.cities.forEach((ele2) => {
nameArr.push(ele2.name);
})
})
return nameArr;
}
getNames(states);
Try this please!
states = [{
name: "telangana",
cities: [{
id: 1,
name: "foo"
}, {
id: 2,
name: "joo"
}, {
id: 3,
name: "goo"
}]
},
{
name: "punjab",
cities: [{
id: 4,
name: "tyu"
}, {
id: 5,
name: "ery"
}, {
id: 6,
name: "doo"
}]
},
{
name: "mumbai",
cities: [{
id: 7,
name: "eee"
}, {
id: 8,
name: "qqq"
}, {
id: 9,
name: "www"
}]
},
]
const wantedArray = []
for(i=0; i < states.length; i++){
for(j=0; j < states[i].cities.length; j++){
wantedArray.push(states[i].cities[j].name)
}
}
console.log(wantedArray)
Just give it an empty array, then you loop through the states indexes, each index in states will have a cities array, then you just need to loop it again in that array to get each name of the cities. From then, you are using the push method that Javascript provides to push it to the empty array.
Here's how I'm doing it in JSFiddle, there will have a better way to do this, too.

Access the sum of multiple arrays in React

const App = () => {
const course = [{
id: 1,
name: 'Half Stack application development',
parts: [
{
name: 'Fundamentals of React',
exercises: 10,
id: 1
},
{
name: 'Using props to pass data',
exercises: 7,
id: 2
},
{
name: 'State of a component',
exercises: 14,
id: 3
}
]
},
{
name: 'Node.js',
id: 2,
parts: [
{
name: 'Routing',
exercises: 3,
id: 1
},
{
name: 'Middlewares',
exercises: 7,
id: 2
}
]
}
]
I am trying to calculate the sum of the exercises in each of the courses so I can get something at the end of each course which says Total exercises: 31 at the end of Half Stack Application Development and total exercises 10: at the end of Node.Js
I have tried
const totals = course.map(c => c.parts.map(c => c.exercises.map(c => c.reduce((a, b) => a + b, 0))))
but received c.exercises.map is not a function.
How could I calculate the sum of each of c.exercises?
exercises looks like this in the console:
(2) [Array(3), Array(2)]
0: (3) [10, 7, 14]
1: (2) [3, 7]
length: 2
This to calculate just the number of exercises per course
const calculateTotalExercises = course =>
course.map(c => c.parts.reduce((res, {
exercises
}) => res + exercises, 0))
const course = [{
id: 1,
name: 'Half Stack application development',
parts: [{
name: 'Fundamentals of React',
exercises: 10,
id: 1
},
{
name: 'Using props to pass data',
exercises: 7,
id: 2
},
{
name: 'State of a component',
exercises: 14,
id: 3
}
]
},
{
name: 'Node.js',
id: 2,
parts: [{
name: 'Routing',
exercises: 3,
id: 1
},
{
name: 'Middlewares',
exercises: 7,
id: 2
}
]
}
]
console.log(calculateTotalExercises(course))
Probably it will be more convenient to add the total of the exercise to the array like this
const calculateTotalExercises = course =>
course.map(c => ({...c, totalExercise : c.parts.reduce((res, p) => res + p.exercises, 0)}))
const course = [{
id: 1,
name: 'Half Stack application development',
parts: [{
name: 'Fundamentals of React',
exercises: 10,
id: 1
},
{
name: 'Using props to pass data',
exercises: 7,
id: 2
},
{
name: 'State of a component',
exercises: 14,
id: 3
}
]
},
{
name: 'Node.js',
id: 2,
parts: [{
name: 'Routing',
exercises: 3,
id: 1
},
{
name: 'Middlewares',
exercises: 7,
id: 2
}
]
}
]
console.log(calculateTotalExercises(course))
You could start by breaking the problem down. Here's how I solved this.
I created a function that finds the total number of exercises for one course
let totalExerciseForOneCourse = (parts) => {
return parts.reduce((prev, curr) => prev + curr.exercises, 0)
}
Then we use the map method to go through each course in the courses array returning a new array of objects with everything that was in the courses array and adding in a totalExercises object property
let newCourses = courses.map((course) => {
const total = totalExerciseForOneCourse(course.parts);
return Object.assign({}, course, {
totalExercises: total
})
})
Our totalExerciseForOneCourse function takes an array parameter and calculates the sum of all exercises for one course using the array.reduce method
newCourses contains our new array with all previous and new information
JSFiddle -
https://jsfiddle.net/swish933/9fwzysxa/
The sum of multiple arrays can be rendered in a single component looking like this
{c.parts.reduce((a, b) => a += b.exercises, 0)}
You can just do
let total = 0
courses.map(course => course.parts.map(part => total += part.exercises)
Edit:
Just in case you need to use reduce:
const total = courses.map(course => course.parts.reduce(e1,e2 => e1+e2 ))

Assign new properties to an array of Objects

I have an array of Objects
const options = [
{ id: 1, name: "Back Pain" },
{ id: 2, name: "Body aches" },
{ id: 3, name: "Cold Sores" },
{ id: 4, name: "Cough" },
{ id: 5, name: "Constipation" },
];
I am trying to write a function that will assign new properties to the object.
The output I am looking for is:
const options = [
{ value: 1, label: "Back Pain" },
{ value: 2, label: "Body aches" },
{ value: 3, label: "Cold Sores" },
{ value: 4, label: "Cough" },
{ value: 5, label: "Constipation" },
];
I have tried to loop through the array using a for loop, but can not figure it out.
Thanks for the help:)
You can do it like this:
const data=[{ id: 1, name: "Back Pain" },
{ id: 2, name: "Body aches" },
{ id: 3, name: "Cold Sores" },
{ id: 4, name: "Cough" },
{ id: 5, name: "Constipation" },
];
var result = data.map(({id:value, name:label})=>({value, label}));
console.log(result);

Join two objects just like SQL inner join

I have two objects like:
countries = [
{ id: 1, name: 'India', image: 'thumb15.jpg' },
{ id: 2, name: 'Africa', image: 'thumb11.jpg' },
{ id: 3, name: 'Kenya', image: 'thumb10.jpg' }
];
cities = [
{ id: 1, name: 'Ahmedabad', country_id: 1 },
{ id: 2, name: 'Vadodara', country_id: 1 },
{ id: 3, name: 'Cairo', country_id: 2 },
{ id: 4, name: 'Kinshasa', country_id: 2 },
{ id: 5, name: 'Luanda', country_id: 2 },
{ id: 6, name: 'Nairobi', country_id: 3 },
{ id: 7, name: 'Nakuru', country_id: 3 },
{ id: 8, name: 'Mombasa', country_id: 3 },
];
I want to combine these two Objects, just like SQL have INNER JOIN
for example, I want to perform below operation (query) on the above two objects,
SELECT * from countries INNER JOIN cities ON cities.country_id = countries.id
and my expected output will look like:
expected_result = [
{ id: 1, name: "Ahmedabad", country_id: 1, country_name: "India", country_image: "thumb15.jpg" },
{ id: 2, name: "Vadodara", country_id: 1, country_name: "India", country_image: "thumb15.jpg" },
{ id: 3, name: "Cairo", country_id: 2, country_name: "Africa", country_image: "thumb11.jpg" },
{ id: 4, name: "Kinshasa", country_id: 2, country_name: "Africa", country_image: "thumb11.jpg" },
{ id: 5, name: "Luanda", country_id: 2, country_name: "Africa", country_image: "thumb11.jpg" },
{ id: 6, name: "Nairobi", country_id: 3, country_name: "Kenya", country_image: "thumb10.jpg" },
{ id: 7, name: "Nakuru", country_id: 3, country_name: "Kenya", country_image: "thumb10.jpg" },
{ id: 8, name: "Mombasa", country_id: 3, country_name: "Kenya", country_image: "thumb10.jpg" }
];
Thanks in advance.
It is possible to use map function and Map collection to get desired country:
const uniqueCountries = new Map(countries.map(s => [s.id, s]));
const result = cities.map(s => ({ ...s,
country_name: uniqueCountries.get(s.country_id).name }));
An example:
let countries = [
{ id: 1, name: 'India', image: 'thumb15.jpg' },
{ id: 2, name: 'Africa', image: 'thumb11.jpg' },
{ id: 3, name: 'Kenya', image: 'thumb10.jpg' }
];
let cities = [
{ id: 1, name: 'Ahmedabad', country_id: 1 },
{ id: 2, name: 'Vadodara', country_id: 1 },
{ id: 3, name: 'Cairo', country_id: 2 },
{ id: 4, name: 'Kinshasa', country_id: 2 },
{ id: 5, name: 'Luanda', country_id: 2 },
{ id: 6, name: 'Nairobi', country_id: 3 },
{ id: 7, name: 'Nakuru', country_id: 3 },
{ id: 8, name: 'Mombasa', country_id: 3 },
];
const uniqueCountries = new Map(countries.map(s => [s.id, s]));
const result = cities.map(s => ({ ...s,
country_name: uniqueCountries.get(s.country_id).name }));
console.log(result);
UPDATE:
map method creates new array from the calling array. In addition, you can add new properties to your object you want:
let countries = [
{ id: 1, name: 'India', image: 'thumb15.jpg' },
{ id: 2, name: 'Africa', image: 'thumb11.jpg' },
{ id: 3, name: 'Kenya', image: 'thumb10.jpg' }
];
const countriesWithShortCountryNames = countries.map(s=> ({...s,
shortName: s.name.substring(0, 3)}))
console.log(countriesWithShortCountryNames)
Map collection:
The Map object holds key-value pairs and remembers the original
insertion order of the keys.
You could take a hash table for all items of countries, where id is the key and the value is a new object in the wanted format.
{
1: {
country_name: "India",
image: "thumb15.jpg"
},
2: {
country_name: "Africa",
image: "thumb11.jpg"
},
3: {
country_name: "Kenya",
image: "thumb10.jpg"
}
}
Then map a new objects with the original key/value and new properties from the hash table.
Methods used, in order of appearance:
Array#reduce
destructuring assignment with assigning to new variable name
Array#map
var countries = [{ id: 1, name: 'India', image: 'thumb15.jpg' }, { id: 2, name: 'Africa', image: 'thumb11.jpg' }, { id: 3, name: 'Kenya', image: 'thumb10.jpg' }],
cities = [{ id: 1, name: 'Ahmedabad', country_id: 1 }, { id: 2, name: 'Vadodara', country_id: 1 }, { id: 3, name: 'Cairo', country_id: 2 }, { id: 4, name: 'Kinshasa', country_id: 2 }, { id: 5, name: 'Luanda', country_id: 2 }, { id: 6, name: 'Nairobi', country_id: 3 }, { id: 7, name: 'Nakuru', country_id: 3 }, { id: 8, name: 'Mombasa', country_id: 3 }],
countriesH = countries.reduce((r, { id, name: country_name, ...o }) =>
(r[id] = { country_name, ...o }, r), {}),
result = cities.map(o => ({ ...o, ...countriesH[o.country_id] }));
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
I wrote a library (which emulates dotnet's linq) which makes this a breeze:
import { blinq } from "blinq";
//...
const joinedData = blinq(countries)
.join(
cities,
co => co.id,
ci => ci.country_id,
(country, city) => ({ country, city })
)
.toArray();
const {
blinq
} = window.blinq;
const countries = [{
id: 1,
name: "India",
image: "thumb15.jpg"
},
{
id: 2,
name: "Africa",
image: "thumb11.jpg"
},
{
id: 3,
name: "Kenya",
image: "thumb10.jpg"
}
];
const cities = [{
id: 1,
name: "Ahmedabad",
country_id: 1
},
{
id: 2,
name: "Vadodara",
country_id: 1
},
{
id: 3,
name: "Cairo",
country_id: 2
},
{
id: 4,
name: "Kinshasa",
country_id: 2
},
{
id: 5,
name: "Luanda",
country_id: 2
},
{
id: 6,
name: "Nairobi",
country_id: 3
},
{
id: 7,
name: "Nakuru",
country_id: 3
},
{
id: 8,
name: "Mombasa",
country_id: 3
}
];
const joinedData = blinq(countries)
.join(
cities,
co => co.id,
ci => ci.country_id,
(country, city) => ({
country,
city
})
)
.toArray();
console.log(JSON.stringify(joinedData, null, 2))
<script src="https://cdn.jsdelivr.net/npm/blinq"></script>

How to properly un-nest and flatten an array of javascript objects with an array inside them (X-amount of times)

I'm currently working with an array of javascript objects with X-amount of array's with the same type of object inside it, in a specific property (in this case, 'modelChildren')
I would like to flatten this into just one array of objects, and return the level at which it was found. The solution does not have to be plain javascript, as I use lodash for many situations. Ideally I would also like to remove the 'modelChildren' field once finished.
Any help would be appreciated.
Thanks!
input:
[{
id: 1,
name: foo
modelChildren: [
{
id: 2,
name: bar,
modelChildren: [
{
id: 3,
name: foobar
},
{
id: 4,
name: foobarfoo
}
]
}
]
}]
expected result:
[{
id: 1,
name: foo,
level: 1
{
id: 2,
name: bar,
level: 2
},
{
id: 3,
name: foobar,
level: 3
},
{
id: 4,
name: foobarfoo
level: 3
}]
This can be quite easy, it is just Tree Traversal
So you just need to traverse it and remember the level, while storing "nodes" when you are in them.
For example this code
const source = [{
id: 1,
name: 'foo',
modelChildren: [
{
id: 2,
name: 'bar',
modelChildren: [
{
id: 3,
name: 'foobar'
},
{
id: 4,
name: 'foobarfoo'
}
]
}
],
}, {
id: 5,
name: 'foo',
modelChildren: [
{
id: 6,
name: 'bar',
modelChildren: [
{
id: 7,
name: 'foobar'
},
{
id: 8,
name: 'foobarfoo'
}
]
},
{
id: 9,
name: 'bar',
modelChildren: [
{
id: 10,
name: 'foobar'
},
{
id: 11,
name: 'foobarfoo'
}
]
}
],
}
];
const newSource = [];
const _ = require('lodash');
function doIt(items, level) {
if (!items) {
return;
}
items.forEach(item => {
newSource.push(_.merge({level}, _.pick(item, ['id', 'name'])));
doIt(item.modelChildren, level + 1);
})
}
doIt(source, 1);
console.log(newSource);
Having this output
[ { level: 1, id: 1, name: 'foo' },
{ level: 2, id: 2, name: 'bar' },
{ level: 3, id: 3, name: 'foobar' },
{ level: 3, id: 4, name: 'foobarfoo' },
{ level: 1, id: 5, name: 'foo' },
{ level: 2, id: 6, name: 'bar' },
{ level: 3, id: 7, name: 'foobar' },
{ level: 3, id: 8, name: 'foobarfoo' },
{ level: 2, id: 9, name: 'bar' },
{ level: 3, id: 10, name: 'foobar' },
{ level: 3, id: 11, name: 'foobarfoo' } ]

Categories