I tried to use Typed arrays instead of arrays, to reduce memory:
function createarrayInt8(numrows,numcols,number){
var arr = new Int8Array(numrows);
for (var i = 0; i < numrows; ++i){
var columns = new Int8Array(numcols);
for (var j = 0; j < numcols; ++j){
columns[j] = number;
}
arr[i] = columns;
}
return arr;
}
But i can't create multidimensional Typed array.
Why?
Do i have to cast only the "number" var to Int8?
A typed Int8Array can only hold 8-bit integers. So arr[i] = columns won't work since columns is of type Int8Array which cannot be converted to and stored (in any meaningful way) as a an 8-bit integer.
Solution: Either make arr a generic Array whose elements can be arrays or - probably the more advanced but usually more performant solution - store your multidimensional array as a single flat array of size numrows * numcols and access an element via arr[column + row * numcols]:
var numrows = 5, numcols = 4;
var arr = new Int8Array(numrows * numcols).fill(0);
arr[3 + 1 * numrows] = 1; // col = 3, row = 1
console.log (arr);
Related
Are there any more efficient ways to create nested objects than nested for approach?
I am trying to hold 25 random numbers (1 - 71), 5 row x 5 column. I will iterate through each item to check if ballPicker() function (not yet implemented) has picked a number that the object has. So I need to keep the information that if a number was found. I could have done it with a 5 x 5 array but iterating that array will not be as efficient as objects.
I have an array starting from 1 to 71 (inclusive, step is 1).
I shuffle the array in createRandomNumberArray() function. So shuffledNumbers array values are not sequential
let shuffledNumbers = Array.from({length: 71}, (v, i) => i + 1);
function createRandomNumberArray() { //Fisher - Yates shuffle algorithm
let randomPosition;
let temp;
for (let i = shuffledNumbers.length - 1; i > 0; i--) {
randomPosition = Math.floor(Math.random() * (i + 1));
temp = shuffledNumbers[i];
shuffledNumbers[i] = shuffledNumbers[randomPosition];
shuffledNumbers[randomPosition] = temp;
}
}
In createBoards() function I am creating an object (board) that holds 5 objects (row) with their indexes as property name. And row has 5 objects (cell) with their indexes as property name again. Cell has only one object that gets its property name from slicedArray(slicedArray is a 5 item slice from shuffledNumbers that holds non duplicated random numbers (range inclusive 1 to inclusive 71)) and its value is always false.
function createBoards() {
let board = {};
for (let i = 0; i < 5; i++) {
let row = {};
let slicedArray = shuffledNumbers.slice((i * 5), ((i + 1) * 5));
for (let j = 0; j < 5; j++) {
let cell = {};
cell[slicedArray[j]] = false;
row[j] = cell;
}
board[i] = row;
}
return board;
}
I want to keep the structure like this:
Board object will have exactly 5 rows and 1 row has exactly 5 items. And in the future I need to iterate those items to find the random value that I had assigned before. I thought it is faster to use objects than arrays. I hope I am correct.
I am trying to create a function that will generate a random number and store it in an array so the first click will send the random number to the index[0] click 2 to index [1] ect. I need to be able to compare the number with the one before (index [4] with index [3].I am sure the answer is right in front of me but i cannot find a solution. Any help would be fantastic
for(i = 0;i < 12;i++) {
var random_number = Math.floor(Math.random() * 12);
var myArray = [];
myArray.push(random_number);
console.log(myArray.length);
document.getElementById("catchme").innerHTML = random_number;
}
});
http://codepen.io/kingnarwal/pen/BzjRjq?editors=1111
var myArray = [];
for(var x = 0, maxValue = 12, random_number; x < 12; x++) {
do {
random_number = Math.floor(Math.random() * maxValue );
} while(random_number == myArray[x - 1]);//Check if the number is the same value
myArray.push(random_number);
}
console.log(myArray);
This does not generate an array with random unique numbers since you're only checking the item before the current item.
To make values unique in whole array:
var myArray = [];
for(var x = 0, maxValue = 12; x < maxValue; x++) {
myArray.splice(Math.floor(Math.random() * myArray.length), 0, x);
}
console.log(myArray);
Above is a bit hackish method since it uses splice with an random index :P
Keep in mind that above method is FAR from random.
A more random method would be:
var myArray = [];
for(var x = 0, x < 12; x++) {
myArray.push(x);
}
shuffle(myArray);
console.log(myArray);
You can use an array shuffle method from here: How to randomize (shuffle) a JavaScript array?
I want to create an array matrix like this:
createMatrix(4);
// logs:
[[0,0,0,0],
[0,0,0,0],
[0,0,0,0],
[0,0,0,0]];
Currently my solution is :
function createMatrix (n) {
var innerArr;
var outerArr = [];
for (var i=0; i<n; i++){
innerArr = [];
for (var j=0; j<n; j++) {
innerArr.push(0);
}
outerArr.push(innerArr);
}
}
console.log(outerArr);
Is there a more efficient way to do this? This will iterate nxn times which is very inefficient for something very simple.
With the ECMAScript 2015 function Array.prototype.fill():
Array(row_count).fill(Array(column_count).fill(0)).map(a => a.slice())
Explanation:
// a sparse array with row_count "absent" items:
Array(row_count)
// an array with column_count members with the value 0:
Array(column_count).fill(0)
// an array with row_count times the identic array as value:
Array(row_count).fill(Array(column_count).fill(0))
// shallow copy the inner array:
Array(row_count).fill(Array(column_count).fill(0)).map(a => a.slice())
Speed?
n=4: http://jsperf.com/creatematrix/1
n=8: http://jsperf.com/creatematrix/2
n=16: http://jsperf.com/creatematrix/3
n=32: http://jsperf.com/creatematrix/4
Seemingly the Array.prototype.fill() variant gets faster as the matrix grows (in relation to the loops). At least in Firefox. YMMV.
There are a couple of approaches you could take:
concat()/slice()
var numCols = 4;
var numRows = 4;
var innerArrSrc = [];
var outerArr = [];
for (var i = 0; i < numCols; i++) {
innerArrSrc.push(0);
}
for (var j = 0; j < numRows; j++) {
outerArr.push(innerArrSrc.concat()); // Could also use innerArrSrc.slice();
}
Both Array.prototype.concat() and Array.prototype.slice() will return a shallow copy of the source array.
one-dimensional array
Alternatively, you could represent your matrix as an one-dimensional array rather than a multi-dimensional one and provide functions to access specific indexes based on row-column values:
var numRows = 4;
var numCols = 4;
var len = numRows * numCols;
var outerArr = [];
for (var i = 0; i < len; i++) {
outerArr.push(0);
}
A function to access a specific index of a matrix represented this way might look like:
function getMatrixIndex(myMatrix, col, row, numCols) {
var index = row * numCols + col;
return myMatrix[index];
}
Array.prototype.fill
If you want to take advantage of new ES6 features Array.prototype.fill should suit your needs:
// Multi-dimensional
var numRows = 4;
var numCols = 4;
var outerArr = new Array(row_count).fill(new Array(column_count).fill(0)).map(a => a.slice());
// Or one-dimensional
var len = numRows * numCols;
var oneDim = new Array(row_count * column_count).fill(0);
jsPerf tests
You can run this jsPerf test to see which is fastest. I've tested in:
Firefox 42.0 32-bit on Windows NT 10.0 64-bit
Chrome 44.0.2403.130 32-bit on Windows NT 10.0 64-bit
Chrome 47.0.2526.73 32-bit on Windows NT 10.0 64-bit
Android Browser 42.0 (Gecko) on Android 6.0
My goal is to make a randomly generated 2D Array in Javascript, that has an X amount of the same one character value while the rest of the values are equal to another character.
In this example, there are 10 rows and 10 columns for the 2D Array. 20 out of the possible 100 values of the Array should be equal to 'Y' (for yes) and the 80 others should be 'N' (for no). I want the 'Y's to be randomly placed all over the Array, and I absolute need exactly 20 of them to be 'Y's and the rest 'N's.
I had a less efficient way before, and I thought to try this approach, where after I define the Array, I make the first X amount of values a 'Y' and then the rest all 'N's. Then I shuffle the array, (using the shuffle from the underscore library) so that the 'Y's are all spread out randomly everywhere.
Is this an efficient way of getting what I need done? Are there any better solutions? I tried making a JSFiddle with my example, but the site appears to be down at the moment.
(I was unable to test my code yet to see if the shuffle worked correctly on my 2D array)
var rows = 10;
var cols = 10;
var elements = 20;
//Define Empty Array
var test = new Array(rows);
for (var k = 0; k < rows; k++)
{
test[k] = Array(cols);
}
var i = 1;
for (var x = 0; x < rows; x++)
{
for (var y = 0; y < cols; y++)
{
if (i <= elements)
{
test[x][y] = "Y";
}
else
{
test[x][y] = "N";
}
}
}
//Shuffle all those values so they're no longer in order
var shuffledTest = _.shuffle(test);
//Print in rows
for (var x = 0; x < rows; x++)
{
console.log(shuffledTest[x]);
}
A very simple solution is to first create an array, fill it with a number of "N"s, insert the "Y"s at random indexes, and then finally splitting it into the 2-dimensional array that you want:
var tmpArr = [], // Temporary 1-dimensional array to hold all values
arr = [], // The final 2-dimensional array
rows = 10,
cols = 10,
elements = 20; // Number of "Y"s
// 1. Fill temporary array with "N"s
for (var i = 0; i < rows * cols - elements; i += 1) {
tmpArr.push("N");
}
// 2. Insert "Y"s at random indexes in the temporary array
for (var i = 0; i < elements; i += 1) {
var index = Math.round(Math.random() * (tmpArr.length + 1));
tmpArr.splice(index, 0, "Y");
}
// 3. Split temporary array into 10 seperate arrays
// and insert them into the final array
for (var i = 0; i < rows; i += 1) {
var row = tmpArr.slice(i * cols, (i + 1) * cols);
arr.push(row);
}
JSBin to illustrate: http://jsbin.com/luyacora/1/edit
You can try this solution, it uses underscores range to create a pair of arrays to use as iterators, though their values don't matter.
Play around with the randomizer function to get an even distribution of 'y's
JSBIN: http://jsbin.com/yaletape/1/
var rows = _.range(0, 10, 0);
var columns = _.range(0, 10, 0);
function randomizer(mult){
return Math.floor((Math.random()*mult)+1);
}
var y_count = 0;
var matrix = _.map(rows, function(){
return _.map(columns, function(v, i){
var value;
var y_allowed = randomizer(3);
var current_y_count = 0;
if(y_count < 20 && current_y_count < y_allowed){
var rand = randomizer(5);
if(rand > 4){
value = 'y';
current_y_count++;
y_count++;
}
}
if(!value){
value = 'n';
}
return value;
});
});
//The above could be simplified to
var matrix = _.range(0,10,0).map(function(){
return _.range(0,10,0).map(function(){
//put the logic code from above here
});
});
Maybe shuflle a 2D array is not the best way. As #Zeb mentioned, here is some code that fill random positions with the 'Y' value. After that, the other positions are filled with 'N'.
http://plnkr.co/edit/avyKfgsgOSdAkRa1WOsk
var arr = [];
var cols = 10;
var rows = 10;
var positions = rows*cols; // 100
var YQty = 10; // only 10 'Y' are needed
// 'Y' values.
for(i = 0; i < YQty; i++)
{
do
{
x = parseInt(Math.random() * cols);
y = parseInt(Math.random() * rows);
filled = false;
if (typeof(arr[x]) == "undefined")
{
arr[x] = [];
}
if (typeof(arr[x][y]) == "undefined")
{
arr[x][y] = 'Y';
filled = true;
}
}
while (!filled);
}
// 'N' values.
for (x = 0; x < cols; x++)
{
if (typeof(arr[x]) == "undefined")
{
arr[x] = [];
}
for (y = 0; y < rows; y++)
{
if (arr[x][y] != 'Y')
{
arr[x][y] = 'N';
}
}
}
Shuffling the multidimensional array is not the best approach. Seeing as any sort is worse than linear time complexity. The easiest solution would be to create your multidimensional array and then set each index value to the char you want the 'rest' of the values to be. Then for 1 -> the number of other char value choose a random index and set that to the char.
Note: If the randomly picked spot has already been changed you need to choose a new one to make sure you have the right amount at the end.
I am trying to convert Java code to Javascript and I am trying to assign data to 3 dimensional array and I am getting "TypeError: can't convert undefined to object " error. Following is my code. Thanks in advance for any help.
var initData = [[2], [12], [2]];
for (var i = 0; i < 12; i++)
{
initData[0][i][0] = -1;
initData[0][i][1] = -1;
initData[1][i][0] = -1;
initData[1][i][1] = -1;
}
[[2], [12], [2]];
That's not a declaration of dimensions, that's four array literals. There are no multidimensional arrays in JS. They're just one-dimensional lists that can contain arbitrary values (including other lists).
To create and fill an array that contains other arrays you have to use the following:
var initData = []; // an empty array
for (var i = 0; i < 2; i++) {
initData[i] = []; // that is filled with arrays
for (var j = 0; j < 12; j++) {
initData[i][j] = []; // which are filled with arrays
for (var k = 0; k < 2; k++) {
initData[i][j][k] = -1; // which are filled with numbers
}
}
}
or, to apply your loop unrolling:
var initData = [[], []]; // an array consisting of two arrays
for (var i = 0; i < 12; i++) {
// which each are filled with arrays that consist of two numbers
initData[0][i] = [-1, -1];
initData[1][i] = [-1, -1];
}
initData is a list of three lists, [2], [12] and [2]. Each one with one element.
In order to init a list(or array), you must do
var initData = [];
Then store in initData another list, like initData[0] = [] and so on... like it's mentioned, arrays/lists in javascript aren't initialized with a limit size.