Let's say you have an array of length 20. You want to access 3 equally spaced indices: 0, 9, 19.
How can you do this with any length of array and any number of sections?
I feel like there must be an elegant way of doing it, but the only way I can think of is finding the section size (var len = 20 / (3 -1)), iterating over the total number of sections (for (var i = 0; i < 3; i++) { var row = data[len * i]; }), and then subtracting one for non-zero indices.
You could try something like this (where console.log is used now you can call your array):
var amount = 3;
var total = 20;
var size = (total - 1) / (amount - 1);
for(var i = 0; i < amount; i++) {
console.log(Math.floor(size * i));
}
There isn't realy a more elegant solution.
Related
I'm sure this is quite a simple programming question however, I cant seem to understand it...
I'm trying to make the console.log print out numbers like this - 1 1 1 1 2 2 2 2 3 3 3 3 4 4 4 4 - one for each line. I thought modulo could be used to make this happen, however, I cant seem to figure out how to use it.
Here is the code:
iteration = 16;
for (var i = 0; i < iteration; i++) {
if(i == iteration%4 )
console.log(i);
}
Yes, you need a single loop.
No, you do not need the remainder operator %. This would give you
0 1 2 3 0 1 2 3 ...
But instead you could divide the actual value by 4 and take the integer value for console.log.
const iteration = 16;
for (let i = 0; i < iteration; i++) {
console.log(Math.floor(i / 4) + 1); // offset for starting with 1
}
I suggest that you use two nested for loops, one for the rows and another one for the columns.
Here's an example of how i would do it:
const columns = 4;
const rows = 4;
//if you want to just console.log each number on a different line
for (let i = 1; i <= rows; i++) {
for (let j = 1; j <= columns; j++) {
console.log(i);
}
console.log("\n");
}
//if you want to add each number to an array, and then log the array
for (let i = 1; i <= rows; i++) {
let columnsArray = [];
columnsArray.length = columns;
columnsArray.fill(i);
console.log(columnsArray);
}
//if you want to just log the numbers, you can spread the array
for (let i = 1; i <= rows; i++) {
let columnsArray = [];
columnsArray.length = columns;
columnsArray.fill(i);
console.log(...columnsArray);
}
//or you could push the arrays in another one, and get a matrix!
const matrix = [];
for (let i = 1; i <= rows; i++) {
let columnsArray = [];
columnsArray.length = columns;
columnsArray.fill(i);
matrix.push(columnsArray);
}
console.log(matrix);
It was not clear the output that you wanted, so i got a little sidetracked and made an example for the different cases that came to my mind.
I wasn't sure how to properly word the title.
I have 2 indexes from a 2D array (x and y) and need to multiply them together to get the index for a second array (1D), however it's not that simple 'cause if x or y equals zero, it'll return zero regardless of the other value.
I could get around this using nested loops shown below:
int count = 0;
for( int i = 0; i < x; i++ )
{
for( int j = 0; j < y; j++ )
{
count++;
}
}
//count now equals desired value
...but that seems awfully impractical.
To me this seems like something that should be incredibly simple and I've put off asking until now, thinking that might be the case.
Let’s use the following data to create an example:
var array_2d = [[0,1,2],[3,4,5]];
var array_1d = [0, 1, 2, 3, 4, 5];
If all of your sub arrays have the same size, you can simply multiply your i index by your sub array’s length, in order to find the corresponding “row” of your 1 dimensional array. Then you can simply add the “column” index of your array.
But this would only work if you are working with width-fixed matrixes.
var sub_dimensional_array_length = 3;
for (var i = 0; i < array_2d.length; i++) {
for (var j = 0; j < array_2d[i].length; j++) {
var array_1d_index = (sub_dimensional_array_length * i) + j;
console.log(array_2d[i][j], array_1d[array_1d_index]);
}
}
In JavaScript, is there a more efficient way of calculating perfect squares working from odd numbers than this (the last perfect square stored in the array perfectSqrs is console.logged):
let n = 999,
oddNums = [],
i;
for (i = 3; i < n; i += 1) {
if (i % 2 !== 0) {
oddNums.push(i);
}
}
let oddLength = oddNums.length;
let perfectSqrs = [1],
j = 0;
while (j < oddLength - 1) {
perfectSqrs[j + 1] = perfectSqrs[j] + oddNums[j];
j += 1;
}
console.log(perfectSqrs[perfectSqrs.length - 1]);
Looks like you just want to generate an array of perfect squares? Perhaps you can do something like this:
var squares = [1];
var numSquares = 100;
for (var i=3; i<numSquares*2; i+=2) {
squares.push(squares[squares.length - 1] + i);
}
console.log(squares);
For people unclear about this algorithm, basically:
1
4 (1+3)
9 (1+3+5)
16 (1+3+5+7)
25 (1+3+5+7+9)
Perfect square is essentially the sum of odd numbers
Nothing to do with JS more with algorithms and logic. You can totally avoid the first loop and also avoid storing (memory efficiency) odd numbers. Start your second loop with 1 and iterate by incrementing by 2 instead of 1 (1,3,5,7,...).
My goal is to create a 2D Array, and assign a unique number from 0 to n for each in Javascript.
For example, if there is 5 rows and 5 cols, I first make an array of values containing the numbers from 0 to 24. I then want to shuffle those numbers and then if the number is less than 10, place a 'Y' for that spot in the Array or a 'N' if it's greater than or equal to 10. The end result should be 15 N's and 10 Y's randomly located.
I have the following code that does that, but I find it really inefficient and was wondering if there was a better way of doing it.
//Define Empty Array
test = new Array(rows);
for (var k = 0; k < rows; k++)
{
test[k] = Array(cols);
}
var values = [];
var index = 0;
var maxVals = (rows * cols);
//If maxVals is equal to 25, then the values array will hold "1,2,3,4, ... 24,25"
while(values.push(index++)<maxVals);
//Shuffle all those values so they're no longer in order
var shuffledValues = _.shuffle(values);
var i = 0;
var smallerThan = 10;
for (var x = 0; x < rows; x++)
{
for (var y = 0; y < cols; y++)
{
//Make all the numbers smaller than 10 a Y
if (shuffledValues[i] < smallerThan)
{
test[x][y] = "Y";
}
else
{
test[x][y] = "N";
}
i++;
}
}
Since you need to iterate over all n = rows×columns elements in your array to set a value your algorithm already has a minimum time complexity of O(n). The loop that creates the indexes array is another n and the shuffle method (if implemented correctly) should shuffle in n as well, so you algorithm is already O(3n) = O(n). While you may be able to reduce the constant factor of 3 it's not going to make any huge difference as your number of rows and columns grows large.
If you don't need exactly a certain number to be "Y" or "N" and just a ratio of them on average then you could do this instead:
var ratio = 0.5; //use your required ratio here
for (var x = 0; x < rows; x++)
{
for (var y = 0; y < cols; y++)
{
test[x][y] = Math.random() < ratio ? "Y" : "N";
}
}
I want to push arrays containing random numbers (0 to 10) into a bigger array once the total of its contents is about to exceed 30. But the output is messed up.
var bigarray = new Array();
var smallarray = new Array();
var randNum = 0;
var total = 0;
for (var i = 0; i<10; i++){
randNum = (10*Math.random()).toFixed(0);
total = total + randNum;
if(total>30) {
bigarray.push(smallarray)
smallarray.length=0;
smallarray.push(randNum);
total = randNum;
} else {
smallarray.push(randNum);
}
}
alert(" BIG ARRAY IS "+bigarray);
two wrong things are visible on the first sight in the code
(1) instead of
randNum = (10*Math.random()).toFixed(0);
you probably want
randNum = Math.floor(11*Math.random());
Math.floor instead of toFixed() - see #kennebec comment
11 instead of 10 to return numbers 0 to 10, as 0 <= Math.random() < 1
(2) the following line pushes (many times) the reference to the same smallarray object.
bigarray.push(smallarray);
In the next step you clear the array with smallarray.length = 0. Because the array is not copied to the bigarray, but only referenced, the generated items are lost.
EDIT: I read your question wrong - the rest of the answer is fixed
You probably want to push the duplicate of the smallarray into bigarray, so replace the line above with the following:
bigarray.push(smallarray.slice(0));
You need another loop inside the main one to populate the smallarray, something like:
var bigarray = new Array();
for (var i = 0; i<10; i++){
// moving the variable declarations inside this loop means they are re-set for each small array
var smallarray = new Array();
// create the first entry for the small array
var randNum = Math.floor(11*Math.random());
var total = randNum;
// loop to populate the small array
while(total <= 30){
smallarray.push(randNum);
randNum = Math.floor(11*Math.random());
total += randNum;
}
bigarray.push(smallarray)
}
I made changes to you code and came up with this.
var bigarray = [];
var smallarray = [];
var randNum = 0;
var total = 0;
for (var i = 0; i < 10; i += 1) {
randNum = Math.floor(10 * Math.random()); // you will never have a value of 10?
total = total + randNum;
if (total > 30) {
bigarray.push(smallarray.slice())
smallarray.length = 0;
smallarray.push(randNum);
total = randNum;
} else {
smallarray.push(randNum);
}
}
alert(" BIG ARRAY IS " + bigarray);
On jsfiddle
Things I changed were:
Ran the code through a beautifier
Changed your use of new Array to []
{} and []
Use {} instead of new Object(). Use [] instead of new Array().
Because Object and Array can be overwritten by the user
Changed ++ to += 1
This pattern can be confusing.
Check out Code Conventions for the JavaScript Programming Language and jslint
Added array.slice when you push smallarray to bigarray, this makes a copy in this case. It is important to understand how javascript works, read Is JavaScript a pass-by-reference or pass-by-value language? Without using slice, which makes a copy as the array only contains primitives, when you set the length of the array to 0, then the data was lost.
Changed your use of number.toFixed to Math.floor so that randNum remains a number
Note: Math.random returns a floating-point, pseudo-random number in the range [0, 1] that is, from 0 (inclusive) up to but not including 1 (exclusive)
Whether your code now produces your expected out, I can not be sure from your description but this should be a good starting point.
var bigarray = new Array();
var smallarray = new Array();
var randNum = 0;
var total = 0;
for (var i = 0; i < 10; i++) {
for (var j = 0; j < smallarray.length; j++) {
total = total + smallarray[j];
}
if (total <= 30)
{
randNum = Math.floor((Math.random() * 10) + 1);
smallarray.push(randNum);
}
else {
bigarray.push(smallarray.slice(0));
smallarray.length = 0;
}
total = 0;
}
alert(" BIG ARRAY IS " + bigarray);