Trying to use 'reduce' instead of regular for loop - javascript

I am trying to get the total 'stargazers_count' from a particular user's github repo. This code, using 'for' loop is working. But I would like to use 'reduce'. I am posting what I tried. Can someone point to me where I am wrong?
The JSON can be viewed with this url,using your github username:
https://api.github.com/users/${your username}/repos
This is the working code using for loop:
axios.get(response.data.repos_url)
.then((res) => {
let starCount = 0;
for(let i=0; i<res.data.length; i++) // find out the total number of github stars
{
starCount += res.data[i].stargazers_count;
}
response.data.NoOfStars = starCount; // add the total stars as a property in response object
This is what I tried with 'reduce':
axios.get(response.data.repos_url)
.then((res) => {
let starCount = 0;
const reducer = (acc, currVal) => acc + currVal.stargazers_count;
arr = res.data;
starCount = arr.reduce(reducer);
This did not work. If I can get a brief explanation of where and why I am wrong, it will be helpful.

You need to provide a starting value for your accumulator, otherwise reduce will assume that the first array element is the starting value and this would lead to a NaN result.
starCount = arr.reduce(reducer,0);

Related

Showing data from an array of objects on React component : TypeError: data.map is not a function

I have now been trying to solve this problem for some days, and it seems like the solution should be just in front of me. But nothing seems to work for me. This is my first React app, so may do somethings completly off... :D
I have this data
const teamNames = ['Sort', 'Gul', 'Blå', 'Rød', 'Orange', 'Grøn']
let [finalTeamData, setFinalTeamData] = useState()
In my function I do like this, first reset the data and then building it.
function makeTeams () {
const playersParticipating = []
let howManyTeams = 0
const teams = []
setFinalTeamData(finalTeamData = [])
// Get the players who is participating
for (let i = 0; i < players.length; i++) {
if (players[i].participating) {
playersParticipating.push(players[i].name)
}
}
// Find the number of players pr team.
howManyTeams = playersParticipating.length / parseInt(teamsize)
// Divide the players out on each team randomly
// Taking 1 team at a time
for (let i = 0; i < howManyTeams; i++) {
teams[i] = []
for (let y = 0; y < teamsize; y++) {
let number = Math.floor(Math.random() * playersParticipating.length)
teams[i].push(playersParticipating[number])
playersParticipating.splice(number, 1)
}
}
console.log(teams)
setShowteams(true)
for (let i = 0; i < teams.length; i++) {
setFinalTeamData(finalTeamData[i] =
{
id: i,
teamname: teamNames[i],
players: teams[i]
}
)
}
console.log(finalTeamData)
}
Passing it into my component here
<ShowTeams data={finalTeamData} />
Lastly here is my component.
const ShowTeams = ({ data }) => {
return (
<>
{data.map((data) => { return <h1>{data.teamname}</h1>;})}
</>
)
}
export default ShowTeams
But no matter how I try to do it, I keep getting this error: TypeError: data.map is not a function
How do I problaly go through my data and display every object on the component?
As far as I can see it should be an array, and it looks correct in the browser console. Hope someone have the time to have a look.
This is happening because the default value of finalTeamData is undefined. When you use useState, it's important to set a default value especially if you're accessing it immediately without checking it.
Reason:
In the initial render of your component, finalTeamData will be undefined even if you run makeTeam before the render. It takes another cycle before the render gets the updated value.
Solution:
const [finalTeamData, setFinalTeamData] = useState([]);
Also, I suggest creating a function that returns the calculated finalTeamData and setting that value using setFinalTeamData.
const makeTeam = () => {
...calculate
return teamData
}
const [finalTeamData, setFinalTeamData] = useState(makeTeam());
This way your default value will be the calculated teams. You might also want to take into account when you want to update the finalTeamData.
Depending on how often it is or if ever the value changes, you can take a look at useEffect to update it.
https://reactjs.org/docs/hooks-effect.html
UPDATE
After reviewing the code again, this snippet concerned me:
setFinalTeamData(finalTeamData[i] =
{
id: I,
teamname: teamNames[i],
players: teams[i]
}
);
You don't want to directly modify the state value and you'd want to use the setter function. Your default value is an array so I would modify this to:
const teamData = [];
for (let i = 0; i < teams.length; i++) {
teamData.push({
id: i,
teamname: teamNames[i],
players: teams[i]
});
}
setFinalTeamData(teamData);
You also don't need this line:
setFinalTeamData(finalTeamData = [])
https://dev.to/koralarts/react-usestate-5h75

How to store components in an array and render them when I need in React?

I want to render x numbers times a specific component according to what the user chooses.
I wrote this function:
const generateShiftsForm = (totalWeeks) => {
const shiftWeeks = 1;
const shiftList = [];
for (let i = shiftWeeks; i === totalWeeks; i++) {
shiftList.push(<ShiftForm totalMinutes={totalMinutes} setTotalMinutes={setTotalMinutes}/>);
}
return shiftList;
};
But when I call it inside the render function it doesn't generate anything unless the totalWeeks is 1.
{generateShiftsForm(shiftNumber).map((form) => (form))}
Why is it like this? I didn't get it, can someone explain it to me?
Seems like there is a typo in the for loop condition - i === totalWeeks, that's why the for loop is being run only once and only if totalWeeks equals 1. Try replacing the for loop you have with the following:
for (let i = shiftWeeks; i <= totalWeeks; i++) {...}

How to get the remainder of multiple array values?

I'm creating something fun for myself just to improve my knowledge and im currently stuck at this problem, where I need to get the remainder of 2 array values.
It's gonna be hard to explain with words, so I'll try my best to write it out. The code below will display 20 lines with numbers, for example, the first numbers are gonna be 1441 and 1468, what I need is to subtract the first number and the second number to get the first numbers results/remainder, which is gonna be 1441-1468, which results to -27, and then the 2nd number is gonna subtract the number 3rd number in the array, which comes after 1468.
Simpler explanation:
1441 - this is the first number, that subtracts the number below
1468 - this is the number, that gets subtracted and as a result you get the sum. Then this number subtracts the number below, which is 1445, and so forth.
1445.
const axios = require('axios');
async function getStats() {
let res = await axios.get(`https://api.faceit.com/stats/api/v1/stats/time/users/57c80380-a00f-47ff-996f-8e541156e3c0/games/csgo?size=20`);
let data = res.data;
return data;
}
getStats()
.then(stats => {
let eloArr = [];
for (let i=0; i < stats.length; i++) {
eloArr.push(stats[i].elo);
console.log(eloArr[i]);
}
});
This is what is understand from your question and try to solve your issue.
const arr = [1441,1468,1445,1512,1621,1000];
let finalAnswer = [];
for(let i = 1;i<arr.length;i++)
{
finalAnswer.push(arr[i-1] - arr[i]);
}
console.log(finalAnswer);
Not totally sure what you want as a final result. Maybe this would work for you.
getStats()
.then(stats => {
let eloArr = [stats[0].elo];
console.log(eloArr[0]);
let total = stats[0].elo;
for (let i = 1; i < stats.length; i++) {
eloArr.push(stats[i].elo);
console.log(stats[i].elo);
total -= stats[i].elo;
}
console.log(total);
});
After some hours of trying to figure this problem out, I settled on the easiest solution. It's not by far the best solution, but works for what I need.
This is what I wanted to get as a final result - https://repl.it/repls/HelpfulNoxiousDigits

JavaScript Pop vs slice methods on an array

I've got a data set that's several hundred elements long. I need to loop through the arrays and objects and determine if the data in them is less than a certain number (in my case, 0). If it is, I need to remove all those data points which are less than zero from the data set.
I've tried .pop and .slice but I'm not implementing them correctly. I was trying to push the bad data into its own array, leaving me with only the good data left.
Here's my JS
for (var i = 0; i < data.length; i++) {
if (data[i].high < 0) {
console.log(data[i].high)
var badData = [];
badData.push(data.pop(data[i].high));
console.log(data[i].high)
}
}
I'd go with .filter():
const result = data.filter(row => row.high > 0);
In case you need the bad results too.
const { good, bad } = data.reduce((acc, row) => {
const identifier = row.high > 0 ? 'good' : 'bad';
acc[identifier].push(row);
return acc;
}, { bad: [], good: [] });

Trying to understand how to use Promise in js

I'm using the native driver for mongoDB. In the db I have about 7 collections and I want create a variable that stores the amount of entries in each collection minus the last collection. Afterwards I want to create another variable that stores the entries of the last collection then I want to pass the variables through the res.render() command and show it on the webpage.
The problem I'm having here is that I'm so used to synchronous execution of functions which in this case goes straight out the window.
The code below is the way I'm thinking, if everything is executed in sync.
var count = 0;
db.listCollections().toArray(function(err,collection){
for(i = 1; i < collection.length;i++){
db.collection(collection[i].name).count(function(err,value){
count = count + value;
})
}
var count2 = db.collection(collection[i].name).count(function(err,value){
return value;
})
res.render('index.html',{data1: count, data2: count2})
})
Obviously this doesn't do want I want to do so I tried playing around with promise, but ended up being even more confused.
You could do something like this with Promises:
Get collection names, iterate over them, and return either count, or entries (if it's the last collection). Then sum up individual counts and send everything to the client.
db.listCollections().toArray()
.then(collections => {
let len = collections.length - 1
return Promise.all(collections.map(({name}, i) => {
let curr = db.collection(name)
return i < len ? curr.count() : curr.find().toArray()
}
))
}
)
.then(res => {
let last = res.pop(),
count = res.reduce((p, c) => p + c)
res.render('index.html', {count, last})
})

Categories