First, I want to thanks to Bails for his answer on question console.time shows different time running the same function. But it still confusing me that how can I compare running time of two different functions
Here's the code I have tried.
function fun1(arr) {
let a = 0
for(let i = 0;i < arr.length; i++) {
a += arr[i]
}
return a
}
function fun2(arr) {
let a = 0
arr.forEach((v) => {
a += v
})
return a
}
let array = []
for(let i = 0;i < 100; i++) {
array.push(Math.random())
}
console.time('fun1')
fun1(array)
console.timeEnd('fun1')
console.time('fun2')
fun2(array)
console.timeEnd('fun2')
We all know that forEach is faster than for. But when I run the code above, I got different results:
Related
i am writing quick sort algorthm, and when i testing my code, the result makes me confused.
RangeError: Maximum call stack size exceeded
at Array.push ()
let arr = [0,-1,1,0,1,-1,100,23,17,56,39,47,23,-34,-56];
export default function quickSort(array){
let len = array.length;
if(len <= 1) return array;
let piviot = array.pop();
let left = [], right = [];
for (let i = 0; i < len; i++) {
if(array[i] < piviot){
left.push(array[i]);
}
else{
right.push(array[i])
}
}
return quickSort(left).concat(piviot,quickSort(right));
}
when i change for loop to forEach, problem is disappeared, but i don't know why.
export default function quickSort(array){
let len = array.length;
if(len <= 1) return array;
let piviot = array.pop();
let left = [], right = [];
array.forEach(item => {
if(item < piviot){
left.push(item)
}
else{
right.push(item);
}
});
return quickSort(left).concat(piviot,quickSort(right));
}
Thanks.
This will work as piviot = array.pop(); changes array size which causes the issue
export default function quickSort(array){
let len = array.length;
if(len <= 1) return array;
let piviot = array.pop();
len = array.length;
let left = [], right = [];
for (let i = 0; i < len; i++) {
if(array[i] < piviot){
left.push(array[i]);
}
else{
right.push(array[i])
}
}
return quickSort(left).concat(piviot,quickSort(right));
}
I won't write the quicksort algorithm for you, but I will explain the behavior:
Why the first piece of code overflows stack
This is very common in recursive functions that never end. You are never reaching the magic
if(len <= 1) return array;
All your function calls end up on the call stack. There is a limit depending on the browser on how many can be called on the stack at the same time. Thus when you reach that limit with recursion (and not only) you overflow the stack.
Why for each works
It doesn't, it just won't overflow your stack. Why? Foreach is a callback. It won't run first and then go to the next line.
Using foreach, you are effectively calling the next recursion with empty arrays and they return automatically.
Problem source
https://www.freecodecamp.org/learn/coding-interview-prep/project-euler/problem-30-digit-n-powers
I am curious as to how I can optimize this code. The goal of the code is to find a sum of all numbers whose digits, when raised to the power n, add to the source number.
```
function digitnPowers(n) {
let newArr = [];
let total = 0;
for (let i = 2; i <= Math.pow(9, n) * n; i++) {
let product = 0;
let thisVar = i.toString().split("");
console.log(thisVar);
for (let j = 0; j < thisVar.length; j++){
product += Math.pow(thisVar[j], n);
console.log(product);
}
if (product === i) {
newArr.push(i);
}
}
for (let i = 0; i < newArr.length; i++){
total += newArr[i];
console.log(total);
}
return total;
}
```
All of the code, when run, come out with the correct answers:
```
digitnPowers(2); = 0
digitnPowers(3); = 1301
digitnPowers(4); = 19316
digitnPowers(5); = 443839
```
The console logs are only present to help me learn to solve this problem. My first step in optimization would be to remove those.
My concern is that when I run this function with 5, the code needs to loop nearly 300,000 times, and this function with 4, nearly 27,000. If n were 6, it'd require 3.1million loops. As of now, the code works, but slowly. Any ideas?
I have three for loop as below to integrate their objects.
The problem is the length of 'cars' array is 20,000.
So it should runs every 20,000 times for finding same id between company.user and cars.
But the id of cars is unique.
Can I reduce this repeat number in JS?
I want to reduce the taking time.
Thank you for reading it.
p.s. I uploaded same question adding the concrete logic inside of for loop.
for (let i = 0; i < company.length; i += 1) {
for (let j = 0; j < company[i].user.length; j += 1) {
for (let k = 0; k < cars.length; k += 1) {
if (company[i].user[j].id === cars[k].id) {
company[i].user[j] = {
...company[i].user[j],
...cars[k]
}
}
}
}
}
If there is only 1 match then use break after you found that item. Imagine you find that item at index 1 for example, then the loop would still continue and do 19998 loops. Because of the information that you know there is only 1 possible match you can break it there.
if (company[i].user[j].id === cars[k].id) {
company[i].user[j] = {
...company[i].user[j],
...cars[k]
}
break;
}
for (let i = 0, leni = company.length;; i < leni ; i += 1) {
for (let j = 0, lenj = company[i].user.length; j < lenj; j += 1) {
for (let k = 0, lenk = cars.length; k < lenk; k += 1) {
if (company[i].user[j].id === cars[k].id) {
company[i].user[j] = {
...company[i].user[j],
...cars[k]
}
break; // match only the first one, then stop searching for cars
}
}
}
}
Answer based on test results from https://jsperf.com/caching-array-length/4
Spread left in base on
https://thecodebarbarian.com/object-assign-vs-object-spread.html
this will optimize your code a little more, but ziga1337 is right, the only effective way is to sort your two objects
// company: [ { user: [ { id: '?1'
// cars: [ { id: '?2'
for (let iCompagny of compagny) {
for (let iUser of iCompagny.user) {
let fCar = cars.find(xCar.id===iUser.id)
if (fCar) Object.assign(iUser, fCar)
}
}
in case there is always a car.id unique to each user.id:
let indexCars = cars.reduce((a,c)=>{ a[c.id]=c; return a },{})
compagny.forEach(iCompagny=>{
iCompagny.user.forEach(iUser=>{ Object.assign(iUser, indexCars[iUser.id]) })
})
How can I run a loop 20 times for an array that have only two entries?
I have the following code
const genders = ['male', 'female'];
const randChoice = arr => {
return arr[Math.floor(Math.random() * arr.length)];
};
const loop = () =>
for (let i = ''; i <= 20; i++) {
const data = randChoice(genders);
if(data === 'male') {
const name = randChoice(maleNames);
people.push(new Data(data, name, lastName))
} else {
const name = randChoice(femaleNames);
people.push(new Data(data, name, lastName))
}
console.log('people', people)
return people;
I have tried some different things but never get it working and looping 20 times.
thanksa for all answers.
But let make this more complex
in thisd case. This will not work
The mistake is at Line 8, when you wrote for (let i = ''; i <= 20; i++), you need to first set the variable i to 0, like this: for (let i = 0; i <= 20; i++).
The whole code for your loop will then be:
for (let i = 0; i < 20; i++) {
const data = randChoice(genders);
// here goes if else statement for gender
}
Another mistake that also #Hasan Balcı has pointed out, is that in your code, the loop runs 21 times instead of 20. Why? Because the variable i starts from 0, and the loop runs until it reaches 20, including when its value is 20!
To correct this, instead of writing for (let i = 0; i <= 20; i++), it will have to be for (let i = 0; i < 20; i++), changing i <= 20 to i < 20!
Hope this helped!
Like this you can iterate loop for 20 times:
const loop = () =>{
for (let i = 0; i < 20; i++) {
const data = randChoice(genders);
console.log(data);
}}
why this code return undefined
I can't spot the reason
function findShort(s){
let splitted = s.split(' ');
let result = splitted[0].length ;
let looped
for (var i=0 ; i++ ; i<splitted.length){
looped = splitted[i].length;
if (looped < result) {return looped}else {return result }}
};
console.log(findShort("bitcoin take over the world maybe who knows perhaps"));
I am supposed to get numbers of smallest word
Your for loop condition and increment are inverted:
for (var i=0 ; i++ ; i<splitted.length){ ...
should instead be:
for (var i = 0; i < splitted.length; i++) { ...
You also have to fix your looping code as it returns in both branches of you inner if statement, which means only a single iteration will run.
If you want to return the length of the smallest word, do this:
function findShort(s) {
let splitted = s.split(' ');
let result = splitted[0].length;
for (let i = 0; i < splitted.length; i++) {
const looped = splitted[i].length;
if (looped < result) {
result = looped;
}
}
return result;
};
console.log(findShort("bitcoin take over the world maybe who knows perhaps"));
Or shorter using Array.prototype.reduce():
function findShortest(s) {
return s.split(/\s+/).reduce((out, x) => x.length < out ? x.length : out, s.length);
};
console.log(findShortest('bitcoin take over the world maybe who knows perhaps'));
Your for-loop implementation is wrong, it is supposed to be:
for (var i=0; i<splitted.length; i++)
Order of condition and increment is wrong in you for loop as well as the code inside the loop,
it will check for the first element only as you have a return in all conditions.
Here's the correct one
function findShort(s) {
let splitted = s.split(' ');
let result = splitted[0].length;
let looped
for (var i = 0; i < splitted.length; i++) {
looped = splitted[i].length;
if (looped < result) { result = looped }
}
return result;
};
console.log(findShort("bitcoin take over the world maybe who knows perhaps"));