I have two arrays with a series of integers. I want to simulate cutting a deck of cards repeatedly to 'shuffle the deck'. I set a cut position and assign everything before the cut in Array A to the start of Array B. I realize I need to use slice to avoid just creating a reference to Array A, but can I use slice on both sides of the equation, i.e. arrayB.slice(0,3) = arrayA.slice(49,52) ?
-
I see slice returns a new array. I'm trying to do this with only two arrays, so I'm wondering how I can copy a slice of an array into my new array at an arbitrary index position. It seems to be just copying reference.Stephen– Stephen2011-08-13 18:48:51 +00:00Commented Aug 13, 2011 at 18:48
4 Answers
It doesn't make much sense to assign anything to a return value of a function like you do in your example.
Try to look into the splice method, it should give you what you need.
Example:
var a = arrayA.splice(0,10); //remove the first 10 elements from arrayA and assign them to a
var b = arrayB.splice(0,10); //see above;
Array.prototype.push.apply(arrayA,b); //add the elements you removed from ArrayB to arrayA
Array.prototype.push.apply(arrayB,a); //see above.
5 Comments
Array.prototype.push() puts them on the end.Array.prototype.push() sets the Array which resulted from the splice as the last element of the Array onto which it was pushed. So you end up with something like [ 1, 2, Array[] ] When I first saw it I thought .push() must be doing something magic I didn't know about and was slightly embarrassed for having suggested .concat(). Upon testing, however, I see that .concat() was correct.I don't know if repeated cuttings really mimics a shuffle, but maybe it's not all you're doing. Anyway, based on what I understand of your description, you want:
arrayB = arrayA.splice(49,52).concat( arrayB );
This should result in a modified arrayB having the pieces which were removed from arrayA in front of what it had previously held.
If you do not want arrayA modified such that what goes to arrayB is no longer in arrayA, then you use Array.prototype.slice() instead of Array.prototype.splice().
Using splice():
var a = [ 'a1', 'a2', 'a3', 'a4' ];
var b = [ 'b1', 'b2', 'b3', 'b4' ];
b = a.splice( 0, 2 ).concat( b );
// a is now: [ 'a3', 'a4' ]
// b is now: [ 'a1', 'a2', 'b1', 'b2', 'b3', 'b4' ]
Operating on both arrays to cause each to receive from the other:
var a = [ 'a1', 'a2', 'a3', 'a4' ];
var b = [ 'b1', 'b2', 'b3', 'b4' ];
var removedFromA = a.splice( 0, 2 );
var removedFromB = b.splice( 0, 2 );
b = removedFromA.concat( b );
a = removedFromB.concat( a );
// a is now: [ 'b1', 'b2', 'a3', 'a4' ]
// b is now: [ 'a1', 'a2', 'b3', 'b4' ]
4 Comments
I'm not really 100% clear from your question if you are looking for a good way to shuffle deck of cards, or if you want more information about slice. For this answer I'll assume the former.
It's actually very easy to get a seemingly-simple thing like shuffling wrong. (Wrong in the sense that your shuffling approach can easily have a bias and make some combinations much more common than others).
A better way to shuffle is to use an algorithm like the Fisher-Yates Shuffling Algorithm.
I did this for a card game I wrote (in Javascript) and here's the code I used:
// this.drawPile is an array of cards
var n = this.drawPile.length;
while (n > 1) {
n--;
var k = Math.floor((n + 1) * Math.random());
var temp = this.drawPile[k];
this.drawPile[k] = this.drawPile[n];
this.drawPile[n] = temp;
}
2 Comments
While this isn't completely relevant if you want to simulate complete randomness when shuffling two sides of the decks, try this...
const shuffle = (arr1, arr2) => {
if(!(arr1 instanceof Array) || !(arr2 instanceof Array)) return [];
let ar1 = arr1.length >= arr2.length ? [...arr1] : [...arr2];
let ar2 = arr1.length >= arr2.length ? [...arr2] : [...arr1];
let x = 0;
for(let i = 0; i < ar1.length; i++) {
if(x > ar2.length-1) break;
ar1.splice(Math.floor(Math.random() * (ar1.length+1)), 0, ar2[x]);
x+=1;
}
return ar1;
};