functional loop given a number instead of an array [duplicate] - javascript

This question already has answers here:
Tersest way to create an array of integers from 1..20 in JavaScript
(16 answers)
Closed 6 years ago.
The community reviewed whether to reopen this question 2 months ago and left it closed:
Original close reason(s) were not resolved
Say I have a number 18, instead of an array, in hand.
What is the best way to create a functional loop in JS given a number X instead of array of X elements?
I can do this:
[1,2,3].forEach(function(){
));
but if I have the number 3
I can do
for(var i = 0; i < 3; i++){
}
but I want that loop to be functional instead

If you have a number and you want to create a loop then you can use the number in limiter condition in the for loop.
for(var i = 0; i < number; i++)
Edit 1: you can use foreach on arrays only, in that case since you have a number already you can create a array of that length and then use the foreach on it.
var foo = new Array(number).fill(0);
foo.foreach()
Also another option is
var N = 18;
Array.apply(null, {length: N}).map(Number.call, Number)
result [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17]
Many more options available in this thread Create a JavaScript array containing 1...N

I don't understand why you want to do this. An equivalent to:
[1,2,3].forEach(function(){ ... ));
Is
var limit = n;
while (--limit) {( // Note: 0 is falsy
function(){ ... }
)(limit);}
Or if you really want to use an array structure, the following will do:
new Array(limit).fill(0).forEach(function(){...});
You might be interested in Myth of the Day: Functional Programmers Don't Use Loops.

Per this question, you can "functionally" iterate over a linear sequence relatively easily using:
Array.apply(null, Array(number)).map(function () {}).forEach(...)
Not sure what advantage this gives you versus a regular for-loop with an index, though it is a neat trick.

Related

Why does my code freeze when using for loop but not specified number loop? [duplicate]

This question already has answers here:
How to make for loops in Java increase by increments other than 1
(13 answers)
Closed 8 months ago.
I figured it out but it sure took me 4 hours. It never caused any errors so I used the debug feature which wasn't much help. Since there was no error I'm unsure what else to look up before I ask my question.
for (var i = 0; i < 300; i+7) { //30:00
var random_x = getRandomInt(0, width-1);
var random_y = getRandomInt(0, height-1);
var sample_color = img.colorAt(random_x, random_y);
Solution: change i+7to i++
I'm still confused on why i+7 works when number of loops are specified but not when ran with infinity loop.
The problem with your code is that you aren't assigning the value to i again.
When you write i++ you basically write a shorthand version of i = i + 1. In your code you write i + 7 which doesn't do anything and basically is an infinite loop. You should have written i = i + 7 to assign a new value to i (or i += 7 for the shorthand version).
either use i=i+7 or i+=7
i=i+7 means you are changing the value of i by adding 7 to it. So after every increment value of i increment by 7.
For better knowledge, refer assignment operators.

Bubblesort algorithm [duplicate]

This question already has answers here:
Bubble sort algorithm JavaScript [closed]
(7 answers)
Closed 2 years ago.
im new in this forum so, if i wrong to post this i apologize. Im learnin Javascript and for training i made this bubblesort algorithm:
var x = [1, 5, 2, 8, 3, 6, 4, 9, 7];
sort(x);
function sort(params) {
var appoggio=0;
for (i=0; i<params.length; i++) {
for (j=0; j<params.length; j++) {
appoggio=params[j];
params[j] = params[j+1];
params[j+1] = appoggio;
}
}
}
console.log(x);
I have made a basic html page where i call this script but it doesn't work and i don't understand why. I try to debugg it inser some alert(params[j]) inside the for cycle but after the first interation the scrpt blocks all the web page. What i have to do?
You are falling in an infinite loop as you push at j+1 even when you hit the end of your list (which increment the length each time). Try to stop at params.length-1.
The if condition is missing!
You need to swap values only if they are not ordered correctly.
Plus, as #MetallimaX said, you need to stop your loop at params.length - 1 to avoid writing outside of the array
Without giving you the answer, which would spoil everything:
for a given number of times (enough that values can bubble all the way) {
for each adjacent values pair (from left to right) {
if the pair is not ordered correctly {
swap both elements()
}
}
}

Reduce the complexity of matching the elements of two arrays

I wrote a code that extracts column headers (the first row in a sheet) from a google sheet and compares them with an array of objects. Each object in the objects array has 3 properties: "question", "answer", and "category". The code compares the header of each column, with the "question" property pf each object in the array.
If they're similar it should add the index of the column as a key to some dictionary and set its value to be an array that holds the answer and the category of that question. No need to much explain why I'm doing this, but briefly I built this logic to be able to grade applicants answers on some questions (hence linking the index of a question to its right answer and to its category). Here is the code:
for (i = 0; i<columnHeaders[0].length; i++){
for (j=0; j<questionsObjects.length; j++){
//Get the current question and convert it to lower case
question = questionsObjects[j].question.toString().toLowerCase();
//Get column header, remove any spaces and new lines from it, and convert it to lower case
columnHeader = columnHeaders[0][i].toString().toLowerCase();
if (isStringSimilar(columnHeader, question)){
//Link the column index to its corresponding question object
var catAndAnswer = [];
catAndAnswer.push (questionsObjects[j].category.toLowerCase());
catAndAnswer.push (questionsObjects[j].rightAnswer.toLowerCase());
columnsQuestionsDictionary[i] = catAndAnswer;
} else {
SpreadsheetApp.getActive().getSheetByName("log").appendRow(["no", columnHeader, question]);
}
}
}
The code runs well, my only problem is complexity, it's very high. In some cases this method takes almost 6 minutes to execute (for this case I had around 40 columns and 7 question objects)! To decouple the nested loops, I thought of concatenating the questions values (of all objects in the questions object array) into 1 single string where I precede each question with its index in the objects array.
For example:
var str = "";
for (j=0; j<questionsObjects.length; j++){
str = str + j + questionsObjects[j].question.toString.toLowerCase();
}
Then, I can have another separate loop through the columns headers, extract each header into a string, then use regex exec method to match that header in the long questions string (str), and if it's found I would get its index in str, then subtract 1 from it to know its index in the objects array. However, it turned out that the complexity of matching a regular expression is O(N) where N is the length of the string we search in (str in this example), given that this will be inside the columns loop, I see that we still get a high complexity that can go to O(N^2).
How can I optimize those nested loops so the code runs in the most efficient way possible?
OK, so I used the way suggested by Nina Schholz in the comments and I moved columnHeader = columnHeaders[0][i].toString().toLowerCase(); to be in the outer loop instead of being in the inner one since it's only needed in the outer one.
The time needed to run the code was reduced from ~295 seconds to ~208 seconds, which is good.
I also tried switching the loops order where I made the outer loop to be the inner one and the inner one to be the outer one and updated the usage of i and j accordingly. I did that because it's always recommended to have the outer loop with less iterations and the inner one with more iterations (according to this resource), and in my case, the loop that iterates over questions object array is always expected to have number of iterations <= the other loop.
This is because if we want to calculate the complexity of 2 nested loops, it'll be (ixj) + i, where i and j represents the number of iterations of the outer and the inner loops, respectively. Switching the loops order won't impact the multiplication part (ixj) but it'll impact the addition part. So, it's always better to have the outer number of iterations smaller than the inner ones.
After doing this the final time of the run became ~202 seconds.
Of course since the loops are switched now, I moved this line to the inner loop: columnHeader = columnHeaders[0][i].toString().toLowerCase();, but at the same time I moved this question = questionsObjects[j].question.toString().toLowerCase(); to be under the outer loop because it's only needed there.

How to choose pseudo-random values in an array javascript [duplicate]

This question already has answers here:
Generate unique number within range (0 - X), keeping a history to prevent duplicates
(4 answers)
Closed 7 years ago.
I know how to sort through an array like this
var rand = myArray[Math.floor(Math.random() * myArray.length)];
but what I am trying to do is use this in a loop to pick values from my array that I haven't picked with this function before.
In other words, let's say my array contains apples, bananas, and oranges. i want to be able to pick all three of those out randomly, but I don't want to pick able to pick out the same one more than once.(I hope this made sense)
You can remove the item from the array, so it will not be selected again
var rand = myArray.length ? myArray.splice(Math.floor(Math.random() * myArray.length), 1)[0] : undefined;
Demo: Fiddle
Note: It will modify the original array, so if you want to keep the original array as it was you need to keep a different copy

compare values in an array to a number in javascript [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 8 years ago.
Improve this question
I am writing a program that determines if a number is between two values in an array.
Here is an example of the array I am using.
var attackArray = new Array (2);
attackArray[0] = new Array("0","1","2","2","2","3","4");
attackArray[1] = new Array("2","3","2","3","2","3","4");
I am using the following code to compare the number against the first two values in the array. I then loop through the array until I find a line that meets the requirements. The number must be >= to the first number and <= the second number.
Here is the code that I am using.
function leveltest ( number)
{
var attack = attackArray.length;
for ( var count = 0 ; count < attack; count ++)
{
if ((number >= Number(attackArray [count][0])) && (number <= Number(attackArray [count][1])))
{
do something ;
}
}
}
If someone can look at my code and explain what I am doing wrong.
I believe you are trying to compare a number to each range of numbers defined by the item values with the same index in element 0 and element 1 of attackArray. If that is right, then the following applies.
The problems present in your code snippet were:
You have the index wrong on line 3. Your third line, attackArray[2] = new Array("1","3","2","3","2","3","4"); is creating a new third element in the attackArray created on the first line. Instead, I think you are wanting to populate the second element of attackArray which should be attackArray[1] = new Array("1","3","2","3","2","3","4"); Or you could use different array syntax as shown below.
In the function, you were using the length of attackArray var attack = attackArray.length;, to control the for loop following. Instead, you will want, var attack = attackArray[0].length; so long as attackArray[0] and attackArray[1] are the same length. You can think of it like this, you were getting your length along the wrong dimension of your array. You were getting the length "down" your array or list of objects, ran than "across" the horizontal dim of your array.
In the function, you are confused on how to loop through the array, and you have this attackArray [count][0] and attackArray [count][1] backwards. Instead they should be attackArray[0][count] and attackArray[1][count]. This will allow you to properly compare your number with each item in element 0 and the item of the same index in element 1.
The following code should be a concise, correct working piece of code to accomplish your goal. You can take and plug this in to jsfiddle.net and it should work in Chrome with the Javascript console used to view the results in the log. Here it is:
var attackArray = [];
attackArray[0] = ["0","0","2","2","2","3","4"];
attackArray[1] = ["1","3","2","3","2","3","4"];
function leveltest (number){
var attack = attackArray[0].length;
for (var count = 0;count < attack;count ++){
if ((number >= Number(attackArray [0][count])) &&
(number <= Number(attackArray [1][count]))) {
console.log(number + " matches at index " + count);
}
}
}
leveltest(2);
Looks like your second element in attackArray has the wrong index.
attackArray[2] = new Array("1","3","2","3","2","3","4");
attackArray.length == 2
you "count" can go up to 1, attackArray[1] is not defined by you.
The second comparation inside the if is wrong. At the second loop it will be attackArray[1][1] and you created an attackArray[0] and attackArray[2].

Categories