2

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 compares arr1[rand] with arr2[i] ?

5 Answers 5

6

Create 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);
Sign up to request clarification or add additional context in comments.

8 Comments

Thanks Paul but I need to keep the values in arr1 there, will update that rand though
There are duplicates in arr1, so removing the picked elements doesn't make sure that there are not duplicates in arr2.
@Guffa Ah I see that, updating my answer now.
@styler I have updated my answer, so that it will keep arr1 unchanged and have only unique values in arr2
Hi Paul, this looks good! 1 question though, I thought for loops had to have a start value, end value and increment?
|
2

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.

Comments

1

See http://bost.ocks.org/mike/shuffle/ for good info on the Fischer/Yates shuffle. For your problem, you could take the first five elements of the shuffled deck.

Comments

1

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] );
    }

Comments

1

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 );

1 Comment

@styler ~ - bitwise complement; ! - negate; look at http://en.wikibooks.org/wiki/JavaScript/Operators

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.