How to loop 2D array in a anti-clock wise fashion? - javascript

Given a 2D array of m x n dimension, how can I loop through them in anti-clockwise fashion?
For example:
matrix = [
[ 1, 2, 3, 4 ],
[ 5, 6, 7, 8 ],
[ 9, 10, 11, 12 ],
[ 13, 14, 15, 16 ]
]
1st loop: 1, 5, 9, 13, 14, 15, 16, 12, 8, 4, 3, 2
2nd loop: 6, 10, 11, 7, 6
I really don't mind if the implementation is given in ruby or js
My current solution is like this:
(1..rotate).each do
bottom_left_corner = i
top_right_corner = j
start_nth_layer = 1; end_nth_layer = matrix.length - 2
matrix.reverse_each do
matrix[bottom_left_corner].unshift(matrix[bottom_left_corner - 1].shift) if bottom_left_corner > 0
matrix[top_right_corner] << matrix[top_right_corner + 1].pop if top_right_corner < matrix.length - 1
bottom_left_corner -= 1; top_right_corner += 1
end
nth_layer(matrix, start_nth_layer, end_nth_layer)
end
Update
The output doesn't format doesn't matter, as long as it outputs the correct order.
Purpose of the problem
The purpose of this problem is traverse these arrays anti-clockwise, layer by layer, until no more layers. For each traversal, we shift the values in anti-clockwise. For example:
Iteration 1: Iteration 2: Iteration 3:
============== ============= ==============
1 2 3 4 2 3 4 8 3 4 8 12
5 6 7 8 1 7 11 12 2 11 10 16
9 10 11 12 => 5 6 10 16 => 1 7 6 15
13 14 15 16 9 13 14 15 5 9 13 14

This is Matrix Layer Rotation problem. Here is my full solution:
function matrixRotation(matrix, rotate) {
var r = matrix.length, c = matrix[0].length;
var depth = Math.min(r,c)/2;
for(var i=0;i<depth;i++) {
var x = i, y = i, n = (r-i*2 - 2)*2 + (c-i*2-2)*2+4, dir = 'down', index=0;
var buf = [];
while(index < n) {
buf.push(matrix[x][y]);
if(dir == 'down') {
if(x+1 >= r-i) {
dir = 'right';
y++;
} else {
x++;
}
} else if(dir == 'right') {
if(y+1 >= c-i) {
dir = 'up';
x--;
} else {
y++;
}
} else if(dir == 'up') {
if(x-1 <= i-1) {
dir = 'left';
y--;
} else {
x--;
}
} else if(dir == 'left') {
y--;
}
index++;
}
var move = rotate%n;
buf = [...buf.slice(buf.length-move), ...buf.slice(0, buf.length-move)]
x = i, y = i, dir = 'down', index = 0;
while(index < n) {
matrix[x][y] = buf[index];
if(dir == 'down') {
if(x+1 >= r-i) {
dir = 'right';
y++;
} else {
x++;
}
} else if(dir == 'right') {
if(y+1 >= c-i) {
dir = 'up';
x--;
} else {
y++;
}
} else if(dir == 'up') {
if(x-1 <= i-1) {
dir = 'left';
y--;
} else {
x--;
}
} else if(dir == 'left') {
y--;
}
index++;
}
}
matrix.map(row => console.log(row.join(' ')));
}
const matrix = [[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12], [13, 14, 15, 16]]
// rotate count
const r = 3
matrixRotation(matrix, r);

This approach should support any sizes of matrix and matrix[n]. Give it a try with various test cases if this works for you.
Note that I ignore any performance defects here.
var arr = [
[ 1, 2, 3, 4 ],
[ 5, 6, 7, 8 ],
[ 9, 10, 11, 12 ],
[ 13, 14, 15, 16 ]
],
result = [];
while ( arr.flat().length ) {
var res = [];
// 1. Left side
arr.forEach(x => res = res.concat( x.splice(0, 1) ));
// 2. Bottom side
if (arr.length) {
res = res.concat( ...arr.splice(arr.length - 1, 1) );
}
// 3. Right side
var tmp = [];
if (arr.flat().length) {
arr.forEach(x => tmp.push( x.splice(arr.length - 1, 1) ));
res = res.concat( ...tmp.reverse() );
}
// 4. Top side
if (arr.length) {
tmp = [].concat( ...arr.splice(0, 1) );
res = res.concat( tmp.reverse() );
}
result.push(res);
}
console.log(result);

I would write this in a layered fashion, writing matrix transposition logic (that is, flipping a matrix over the northwest-southeast diagonal), using that and a simple reverse to build a counter-clockwise rotation of the matrix, using that rotation to build a clockwise spiral, and finally using transpose again alongside the clockwise spiral to build a counter-clockwise spiral.
I chose this order because a clockwise spiral is more commonly requested, but it would be easy enough to build the counterclockwise spiral directly. Hint: rotateClockwise = m => transpose(reverse(m)).
const reverse = a => [...a].reverse();
const transpose = m => m[0].map((c, i) => m.map(r => r[i]))
const rotateCounter = m => reverse(transpose(m))
const spiralClockwise = m => m.length < 2
? m[0]
: m[0].concat(spiralClockwise(rotateCounter(m.slice(1))))
const spiralCounter = m => spiralClockwise(transpose(m))
console.log(spiralCounter([
[1, 2, 3, 4],
[5, 6, 7, 8],
[9, 10, 11, 12]
]))
Note that the intermediate functions here are quite possibly useful in their own right. So this strikes me as a good way to break down the problem.

This is how I went about it in ruby:
def counter_clockwise!(arr)
return arr if arr.size <= 1
rotation = [
arr.map(&:shift)
.concat(arr.pop,
arr.map(&:pop).reverse,
arr.shift.reverse).compact
]
rotation.push(*send(__method__,arr)) unless arr.all?(&:empty?)
rotation
end
def counter_clockwise(arr)
counter_clockwise!(arr.map(&:dup))
end
Example:
arr = [
[ 1, 2, 3, 4 ],
[ 5, 6, 7, 8 ],
[ 9, 10, 11, 12 ],
[ 13, 14, 15, 16 ],
[ 17, 18, 19, 20 ],
[ 21, 22, 23, 24 ]
]
counter_clockwise(arr)
#=> [[1, 5, 9, 13, 17, 21, 22, 23, 24, 20, 16, 12, 8, 4, 2, 3],
# [6, 10, 14, 18, 19, 15, 11, 7]]
This method recursively processes the outside edges into groups ("Loops" in your original post). Obviously if you just wanted the counter clockwise spiral without the groups you could flatten the return value.
This will also process non M x N Matrices such as:
arr = [
[ 1, 2, 3, 4 , 72 ],
[ 5, 6, 7, 8 , 73 ],
[ 9, 10, 11 , 12 ],
[ 13, 14, 16 , 75 ],
[ 17, 18, 19, 20 , 76 ],
[ 21, 22, 23, 24 , 77 ]
]
counter_clockwise(arr)
#=> [[1, 5, 9, 13, 17, 21, 22, 23, 24, 77, 76, 75, 12, 73, 72, 4, 3, 2],
# [6, 10, 14, 18, 19, 20, 16, 11, 8, 7]]
If you want each edge and can guarantee M x N then this will work too
def counter_clockwise_edges(arr)
return arr if arr.size == 1
arr = arr.transpose
[arr.shift].push(*send(__method__,arr.map(&:reverse)))
end
counter_clockwise_edges(arr)
#=> [[1, 5, 9, 13, 17, 21],
[22, 23, 24],
[20, 16, 12, 8, 4],
[3, 2],
[6, 10, 14, 18],
[19, 15, 11, 7]]

The following is a modification of my answer to this SO question, which differs from this one only in that the array is traversed in the opposite direction.
arr = matrix.map(&:dup).transpose
out = []
loop do
out = out + arr.shift
break out if arr.empty?
arr = arr.transpose.reverse
end
#=> [1, 5, 9, 13, 14, 15, 16, 12, 8, 4, 3, 2, 6, 10, 11, 7]
The steps are as follows.
arr = matrix.map(&:dup).transpose
#=> [[1, 5, 9, 13], [2, 6, 10, 14], [3, 7, 11, 15], [4, 8, 12, 16]]
I've duped the elements of matrix so that the latter will not be mutated.
out = []
out = out + arr.shift
#=> [1, 5, 9, 13]
arr
#=> [[2, 6, 10, 14], [3, 7, 11, 15], [4, 8, 12, 16]]
arr = arr.transpose.reverse
#=> [[14, 15, 16], [10, 11, 12], [6, 7, 8], [2, 3, 4]]
out = out + arr.shift
#=> [1, 5, 9, 13, 14, 15, 16]
arr
#=> [[10, 11, 12], [6, 7, 8], [2, 3, 4]]
arr = arr.transpose.reverse
#=> [[12, 8, 4], [11, 7, 3], [10, 6, 2]]
out = out + arr.shift
#=> [1, 5, 9, 13, 14, 15, 16, 12, 8, 4]
arr
#=> [[11, 7, 3], [10, 6, 2]]
arr = arr.transpose.reverse
#=> [[3, 2], [7, 6], [11, 10]]
out = out + arr.shift
#=> [1, 5, 9, 13, 14, 15, 16, 12, 8, 4, 3, 2]
arr
#=> [[7, 6], [11, 10]]
arr = arr.transpose.reverse
#=> [[6, 10], [7, 11]]
out = out + arr.shift
#=> [1, 5, 9, 13, 14, 15, 16, 12, 8, 4, 3, 2, 6, 10]
arr
#=> [[7, 11]]
arr = arr.transpose.reverse
#=> [[11], [7]]
out = out + arr.shift
#=> [1, 5, 9, 13, 14, 15, 16, 12, 8, 4, 3, 2, 6, 10, 11]
arr
#=> [[7]]
arr = arr.transpose.reverse
#=> [[7]]
out = out + arr.shift
#=> [1, 5, 9, 13, 14, 15, 16, 12, 8, 4, 3, 2, 6, 10, 11, 7]
arr
#=> []
As arr is now empty we break and return out.
arr
arr = arr.transpose.reverse
out = out + arr.shift
arr
arr = arr.transpose.reverse
out = out + arr.shift
arr
arr = arr.transpose.reverse
out = out + arr.shift
arr
arr = arr.transpose.reverse
out = out + arr.shift
arr
arr = arr.transpose.reverse
out = out + arr.shift
arr
arr = arr.transpose.reverse

Given the array:
array =
[
[ '00', '01', '02', '03', '04', '05'],
[ '10', '11', '12', '13', '14', '15'],
[ '20', '21', '22', '23', '24', '25'],
[ '30', '31', '32', '33', '34', '35']
]
This returns the external loop:
external_ccw_round = [array.map(&:shift), array.pop, array.map(&:pop).reverse, array.shift.reverse].flatten
#=> ["00", "10", "20", "30", "31", "32", "33", "34", "35", "25", "15", "05", "04", "03", "02", "01"]
Leaving just the core
array #=> [["11", "12", "13", "14"], ["21", "22", "23", "24"]]
For matrix with more than one row.
This is a method with a recursive implementation
Works on any matrix 2D.
def ccw_scan(array, result=[])
return array if array.size <= 1
result << [array.map(&:shift), array.pop, array.map(&:pop).reverse, array.shift.reverse]
if array.size >= 2
then ccw_scan(array, result)
else result << array
end
result.flatten.compact
end
Call the method on the array:
ccw_scan(array)
#=> ["00", "10", "20", "30", "31", "32", "33", "34", "35", "25", "15", "05", "04", "03", "02", "01", "11", "21", "22", "23", "24", "14", "13", "12"]

Related

Mutating elements in an array in Javascript

Ok so I want to subtract 9 to numbers(elements in an array) over 9:
finalCredDigits = [10, 8, 18, 9, 16, 6, 16, 5, 14, 3, 14, 6, 10, 5, 8]
Thats what I tried
finalCredDigits.forEach(arr =>{
if(arr > 9){
finalCredDigits.push(arr - 9);
}
});
Output = [10, 8, 18, 9, 16, 6, 16, 5, 14, 3, 14, 6, 10, 5, 8, 1, 9, 7, 7, 5, 5, 1]
I know its cuz the result is being pushed in the array but i want to mutate it and replace the answer with numbers over 9
If you want a similar but new array, you should use Array.map():
const finalCredDigits = [10, 8, 18, 9, 16, 6, 16, 5, 14, 3, 14, 6, 10, 5, 8];
const newFinalCredDigits = finalCredDigits.map(v => {
if (v > 9) {
return v - 9;
} else {
return v;
}
});
console.log(newFinalCredDigits.join());
console.log("Is new array?", newFinalCredDigits !== finalCredDigits);
If you want to mutate the array itself with Array.forEach(), you should use the callback's additional parameters:
const finalCredDigits = [10, 8, 18, 9, 16, 6, 16, 5, 14, 3, 14, 6, 10, 5, 8];
finalCredDigits.forEach((v, i, array) => {
if (v > 9) {
array[i] = v - 9;
}
});
console.log(finalCredDigits.join());
But functional programming usually implies preferring immutable over mutable states, so if your array is shared and we'd mutate it with Array.forEach(), it would be considered a code smell. Therefore I'd use a regular for-loop instead:
const finalCredDigits = [10, 8, 18, 9, 16, 6, 16, 5, 14, 3, 14, 6, 10, 5, 8];
{
const l = finalCredDigits.length;
for (let i = 0; i < l; ++i) {
if (finalCredDigits[i] > 9) finalCredDigits[i] -= 9;
}
}
console.log(finalCredDigits.join());
You need to assign to the array index to replace the element, not push a new element.
forEach() passes a second argument to the callback function, containing the current index. You can use this for the assignment.
const finalCredDigits = [10, 8, 18, 9, 16, 6, 16, 5, 14, 3, 14, 6, 10, 5, 8];
finalCredDigits.forEach((el, i) =>{
if(el > 9){
finalCredDigits[i] = el - 9;
}
});
console.log(finalCredDigits);
Try this
let finalCredDigits = [10, 8, 18, 9, 16, 6, 16, 5, 14, 3, 14, 6, 10, 5, 8]
finalCredDigits = finalCredDigits.map(number => {
if (number > 9) {
return number - 9
}
return number
})
console.log(finalCredDigits)

How to remove last element from every row of a matrix in javascript

I am trying to remove the last element from every row of a matrix in javascript. I am trying to use the "map" function but I am not successful.
Here is my code:
var matrixWithExtraInfo = [
[1, 2, 3, 4, "dog"],
[5, 6, 7, 8, "dog"],
[9, 10, 11, 12, "dog"],
[13, 14, 15, 16, "dog"],
[17, 18, 19, 20, "dog"]
];
var conciseMatrix = [
[1, 2, 3, 4],
[5, 6, 7, 8],
[9, 10, 11, 12],
[13, 14, 15, 16],
[17, 18, 19, 20]
]
var conciseMatrix = matrixWithExtraInfo.map(function(index) {
console.log(index)
matrixWithExtraInfo[index].pop();
return matrixWithExtraInfo[index];
});
console.log(matrixWithExtraInfo);
I get
TypeError: Cannot read property 'pop' of undefined
The first argument to .map is the item you're iterating over, not the index.
Since each item here is an array, you can either .pop the array (which will mutate the existing array), or .slice the array (which will not mutate the existing array).
var matrixWithExtraInfo = [
[1,2,3,4,"dog"],
[5,6,7,8,"dog"],
[9,10,11,12,"dog"],
[13,14,15,16,"dog"],
[17,18,19,20,"dog"]
];
var conciseMatrix = [
[1,2,3,4],
[5,6,7,8],
[9,10,11,12],
[13,14,15,16],
[17,18,19,20]
]
var conciseMatrix = matrixWithExtraInfo.map((arr) => {
arr.pop();
return arr;
});
console.log(matrixWithExtraInfo);
console.log(conciseMatrix);
(the above is weird - the structure you need is already in matrixWithExtraInfo, making another variable to hold it is confusing, but this is the closest to your original code)
var matrixWithExtraInfo = [
[1,2,3,4,"dog"],
[5,6,7,8,"dog"],
[9,10,11,12,"dog"],
[13,14,15,16,"dog"],
[17,18,19,20,"dog"]
];
var conciseMatrix = [
[1,2,3,4],
[5,6,7,8],
[9,10,11,12],
[13,14,15,16],
[17,18,19,20]
]
var conciseMatrix = matrixWithExtraInfo.map(arr => arr.slice(0, -1));
console.log(matrixWithExtraInfo);
console.log(conciseMatrix);
If you want to mutate the existing array, an easy way is to use Array.forEach() to apply Array.pop() to each element:
var matrixWithExtraInfo = [
[1, 2, 3, 4, "dog"],
[5, 6, 7, 8, "dog"],
[9, 10, 11, 12, "dog"],
[13, 14, 15, 16, "dog"],
[17, 18, 19, 20, "dog"]
];
matrixWithExtraInfo.forEach(arr => arr.pop());
console.log(matrixWithExtraInfo);
Otherwise, just use Array.slice():
var matrixWithExtraInfo = [
[1, 2, 3, 4, "dog"],
[5, 6, 7, 8, "dog"],
[9, 10, 11, 12, "dog"],
[13, 14, 15, 16, "dog"],
[17, 18, 19, 20, "dog"]
];
var conciseMatrix = matrixWithExtraInfo.map(arr => arr.slice(0, -1));
console.log(conciseMatrix);
Map will return the element so by iterating all rows we just pop the element which will remove the last element from the each row. As we need a new matrix in different array we should use slice(not pop/splice) which will return the elements in new array and not modifying original matrix.
var matrixWithExtraInfo = [
[1,2,3,4,"dog"],
[5,6,7,8,"dog"],
[9,10,11,12,"dog"],
[13,14,15,16,"dog"],
[17,18,19,20,"dog"]
];
var conciseMatrix = [
[1,2,3,4],
[5,6,7,8],
[9,10,11,12],
[13,14,15,16],
[17,18,19,20]
]
var conciseMatrix = matrixWithExtraInfo.map(row => row.slice(0, row.length-1));
console.log(matrixWithExtraInfo);
console.log(conciseMatrix);
Just adding _, in map function in your code should fix. function(_,index)
var matrixWithExtraInfo = [
[1, 2, 3, 4, "dog"],
[5, 6, 7, 8, "dog"],
[9, 10, 11, 12, "dog"],
[13, 14, 15, 16, "dog"],
[17, 18, 19, 20, "dog"]
];
var conciseMatrix = [
[1, 2, 3, 4],
[5, 6, 7, 8],
[9, 10, 11, 12],
[13, 14, 15, 16],
[17, 18, 19, 20]
]
var conciseMatrix = matrixWithExtraInfo.map(function(_,index) {
console.log(index)
matrixWithExtraInfo[index].pop();
return matrixWithExtraInfo[index];
});
console.log(matrixWithExtraInfo);

Restructure one dimensional array into variable length two dimension array

I am trying to convert a one dimensional array into a two dimensional array where the length of the rows are different depending on the maximum number of columns which is supplied as an argument. I basically want to include every nth index till the end of array is reached or max number of columns are done whatever happens earlier. So for the following input:
arr = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18,
19, 20]
columns = 7
I want the following output:
[1, 4, 7, 10, 13, 16, 19]
[2, 5, 8, 11, 14, 17, 20]
[3, 6, 9, 12, 15, 18]
I have tried the following code but it only works for few values:
var array = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20];
function getOutput(arr, columns) {
var rows = Math.ceil(arr.length / columns);
var res = [];
for (var i = 0; i < rows; i++) {
tmp = [];
for (var j = 0, index = i; j < columns; j++) {
if (index < arr.length)
tmp.push(arr[index]);
index += rows;
}
res.push(tmp);
}
return res;
}
console.log(getOutput(array, 7))
JSFiddle available here: https://jsfiddle.net/varunsharma38/fwfz4veo/4/
I do not understand what I am missing. Although, I would not mind using some libraries, I would prefer a vanilla JS based solution.
Thanks in advance!!
Here is another solution using array#reduce.
var arr = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20],
columns = 7,
result = arr.reduce((r,v,i,a) => {
var index = i% (Math.ceil(a.length/columns));
r[index] = r[index] || [];
r[index].push(v);
return r;
},[]);
console.log(result);

Find valid positions in a board

I'm looking at solving the Puzzle 15 game. Example.
Basically at each position, valid positions can only come vertically or horizontally. I am looking for an algorithm that can determine it at any given position in a board of 16 elements, 4 by 4.
Currently I have the positions hard coded
var rules = [
{ "0": [1, 4]},{ "1": [0, 2, 5] },{ "2": [1, 3, 6] },{ "3": [2, 7] },
{ "4": [0, 5, 8] },{ "5": [1, 4, 6, 9] },{ "6": [2, 5, 7, 10] },{ "7": [3, 6, 11] },
{ "8": [4, 9, 12] },{ "9": [5, 8, 10, 13]},{ "10": [6, 9, 11, 14] },{ "11": [7, 10, 15] },
{ "12": [8, 13] },{ "13": [12, 9, 14] },{ "14": [10, 13, 15] },{ "15": [11, 14] },
]
For example at position "0", only positions [1, 4] are valid to move from.
[ _, 1, 2, 3 ]
[ 4, 5, 6, 7 ]
[ 8, 9, 10, 11 ]
[ 0, 12, 13, 14 ]
What's a better way?
I'm not sure if I 100% understand your problem, but i hope this helps.
If I understand correctly:
You need a function that will tell you, which cells can be moved.
A cell can be moved only if its a direct neighbor of the empty cell.
i would suggest something like this:
// game grid, empty-cell = -1
const grid = [
[ 1, 2, 3, 4],
[ 5, 6, 7, 8],
[ 9, 10, 11, 12],
[13, 14, -1, 15],
]
// Gets value from grid, return null when outside of array
function getCellValue(grid, row, col) {
if (grid[row] === undefined) return null;
if (grid[row][col] === undefined) return null;
return grid[row][col];
}
// Returns array of [row, col] cells,
// that are direct neighbors of the empty cell
function getEmptyCellNeighbors(grid) {
let cells = [];
grid.forEach((cols, row) => {
cols.forEach((value, col) => {
if (getCellValue(grid, row - 1, col) === -1) cells.push([row, col]);
if (getCellValue(grid, row + 1, col) === -1) cells.push([row, col]);
if (getCellValue(grid, row, col - 1) === -1) cells.push([row, col]);
if (getCellValue(grid, row, col + 1) === -1) cells.push([row, col]);
})
})
return cells;
}
// The empty cell(-1) is at[row = 3, col = 2]
// You can move 11, 14, 15 to the empty cell.
// The cuntion will return the[row, col] of cells 11, 14 & 15
console.log(getEmptyCellNeighbors(grid));
// returns => [
// [2, 2], // 11
// [3, 1], // 14
// [3, 3], // 15
// ]

jquery multidimensional array shuffle random

I want to minimize my code from:
myArrayA = [1, 2, 3, 4, 5];
fisherYates(myArrayA);
myArrayB = [6, 7, 8, 9, 10];
fisherYates(myArrayB);
myArrayC = [11, 12, 13, 14, 15];
fisherYates(myArrayC);
myArrayD = [16, 17, 18, 19, 20];
fisherYates(myArrayD);
myArrayE = [21, 22, 23, 24, 25];
fisherYates(myArrayE);
To:
var multArr = [[1, 2, 3, 4, 5], [6, 7, 8, 9, 10], [11, 12, 13, 14, 15], [16, 17, 18, 19, 20], [21, 22, 23, 24, 25]];
fisherYates(multArr);
The output I want is like this:
[4,2,3,5,1],[7,10,6,9,8],[11,15,12,14,13],[18,17,16,20,19],[22,21,25,23,24]
I tried this code:
http://jsfiddle.net/arrow/yFn8U/
function fisherYates(myArray) {
var i = myArray.length, j, tempi, tempj;
if (i === 0) return false;
while (--i) {
j = Math.floor(Math.random() * (i + 1));
tempi = myArray[i];
tempj = myArray[j];
myArray[i] = tempj;
myArray[j] = tempi;
}
}
var multArr = [[1, 2, 3, 4, 5], [6, 7, 8, 9, 10], [11, 12, 13, 14, 15], [16, 17, 18, 19, 20], [21, 22, 23, 24, 25]];
fisherYates(multArr);
But my code only randomizes the order of the chunks not the values in each chunk.
The output I want is like this:
[4,2,3,5,1],[7,10,6,9,8],[11,15,12,14,13],[18,17,16,20,19],[22,21,25,23,24]
I want each chunk inside the array to be in the same order but each chunk must be randomized.
Is there a way to do this with jQuery?
I also wonder how to get values from the shuffled/randomized array?
At the moment I get the values like this:
myArrayA[i]
myArrayB[i]
myArrayC[i]
myArrayD[i]
myArrayE[i]
I would guess I will get them with something like:
multArr [[0][i]];
multArr [[1][i]];
multArr [[2][i]];
multArr [[3][i]];
multArr [[4][i]];
Finally I wonder if minimizing the code will give better performance?
If you simply want to run an operation over all the elements in an array, then you should use map or forEach. I'm sure jquery provides shims for these methods in older browsers. So if we assume you're using your original fisherYates function unaltered, we might have something like this:
var multArr = [[1, 2, 3, 4, 5], [6, 7, 8, 9, 10], [11, 12, 13, 14, 15], [16, 17, 18, 19, 20], [21, 22, 23, 24, 25]];
multArr.forEach(fisherYates);
On accessing the elements, you're almost right, but you have one set too many of brackets :
multArr[1]; // == [6, 7, 8, 9, 10]
multArr[1][3]; // == 9
I wouldn't speculate about the performance, if you're really worried you should put together a jsperf test case.
All you need is jQuery's .each() method, like so:
$.each(multArr, function(i) { fisherYates(this) });
See console on this working example
Fiddle Code
function fisherYates(myArray) {
var i = myArray.length, j, tempi, tempj;
if (i === 0) return false;
while (--i) {
j = Math.floor(Math.random() * (i + 1));
tempi = myArray[i];
tempj = myArray[j];
myArray[i] = tempj;
myArray[j] = tempi;
}
}
$(function() {
$("button").on("click", function(e) {
multArr = [[1, 2, 3, 4, 5], [6, 7, 8, 9, 10], [11, 12, 13, 14, 15], [16, 17, 18, 19, 20], [21, 22, 23, 24, 25]];
$.each(multArr, function(i) { fisherYates(this) });
console.log(multArr)
})
})
Check out my code here. Basically just looped over the elements of the multidimensional array and run the fisherYates on them like so:
function fisherYates(myArray) {
for(var i = 0; i< myArray.length; i++) {
k = myArray[i].length;
while(k--){
j = Math.floor(Math.random() * (myArray.length - 1));
tempk = myArray[i][k];
tempj = myArray[i][j];
myArray[i][k] = tempj;
myArray[i][j] = tempk;
}
}
}
Now if you wanted to do this for an n-dimensional array you're going to have to do it recursively, which would be fun, but I think that is more than you were asking for. If not I can update it later.

Categories