I was wondering if anyone can advise how I can make sure the random array I'm generating from another array doesn't contain duplicate values, want to make sure that arr2 contains unique values?
JS
var limit = 5,
i = 0,
arr1 = [12, 14, 67, 45, 8, 45, 56, 8, 33, 89],
arr2 = [];
for ( i; i < limit; i++ ){
var rand = Math.floor((Math.random()*9)+1);
arr2.push( arr1[rand] );
}
console.log(arr2);
Maybe an if statement that pares arr1[rand] with arr2[i] ?
I was wondering if anyone can advise how I can make sure the random array I'm generating from another array doesn't contain duplicate values, want to make sure that arr2 contains unique values?
JS
var limit = 5,
i = 0,
arr1 = [12, 14, 67, 45, 8, 45, 56, 8, 33, 89],
arr2 = [];
for ( i; i < limit; i++ ){
var rand = Math.floor((Math.random()*9)+1);
arr2.push( arr1[rand] );
}
console.log(arr2);
Maybe an if statement that pares arr1[rand] with arr2[i] ?
Share Improve this question edited Jun 14, 2012 at 16:08 Paul 142k28 gold badges284 silver badges271 bronze badges asked Jun 11, 2012 at 16:41 stylerstyler 16.5k25 gold badges85 silver badges139 bronze badges5 Answers
Reset to default 6Create a temporary array that is a copy of arr1 containing only unique values:
// Copy unique values in arr1 into temp_arr
var temp_obj = {}, temp_arr = [], i;
for(i = arr1.length; i--;)
temp_obj[arr1[i]] = 1;
for(i in temp_obj)
temp_arr.push(i);
Then you can remove the element from temp_arr
each time you add it to arr2
. Since we used object keys when copying we have strings, so we can use +
to convert them back to numbers when pushing into arr2
:
arr2.push(+temp_arr.splice(rand, 1)[0]);
You should also change how you pick random numbers to:
var rand = Math.floor(Math.random()*temp_arr.length);
Whole code:
var limit = 5,
arr1 = [12, 14, 67, 45, 8, 45, 56, 8, 33, 89],
arr2 = [],
rand,
temp_obj = {},
temp_arr = []
i;
// Copy unique values from arr1 into temp_arr
for(i = arr1.length; i--;)
temp_obj[arr1[i]] = 1;
for(i in temp_obj)
temp_arr.push(i);;
// Move elements one at a time from temp_arr to arr2 until limit is reached
for (var i = limit; i--;){
rand = Math.floor(Math.random()*temp_arr.length);
arr2.push(+temp_arr.splice(rand, 1)[0]);
}
console.log(arr2);
The naive O(n^2)
solution is to simply check each element and see if any other position in the array has the same value.
A linear time solution can be achieved using a hashset data structure. You can hack one in JavaScript using objects:
var set = {};
set['0'] = true;
set['1'] = true;
if(set.hasOwnProperty('0')) {
alert("duplicate 0!");
}
If the numbers are integers and relatively small, then you can keep track of them in an array of boolean values.
See http://bost.ocks/mike/shuffle/ for good info on the Fischer/Yates shuffle. For your problem, you could take the first five elements of the shuffled deck.
try this
for ( i; i < limit; i++ ){
var rand = Math.floor((Math.random()*9)+1);
for(j=0; j < arr1.length; j++)
if(rand == arr1[j]
{
blnfound = true;
break;
}
if(!blnfound)
arr2.push( arr1[rand] );
}
By using jQuery.inArray
function :)
var limit = 5,
arr1 = [12, 14, 67, 45, 8, 45, 56, 8, 33, 89],
l = arr1.length,
arr2 = [];
while( limit ){
var tmp = arr1[ Math.random() * l | 0 ];
// for unsigned numbers '|0' construction works like Math.floor
if( !~$.inArray( tmp, arr2 ) ) {
// if not found $.inArray returns -1 ( == ~0 ), then !~-1 == true
limit--;
arr2[ arr2.length ] = tmp;
}
}
console.log( arr2 );