Skip to content Skip to sidebar Skip to footer

Getting Random Unique From Array

I am working on this demo. How can I get ONLY unique selection(s) from the array of cars

Solution 1:

Implementing this as a generator makes it pretty nice to work with. Note, this implementation differs from ones that require the entire input array to be shuffled first.

This sample function works lazily, giving you 1 random item per iteration up to N items you ask for. This is nice because if you just want 3 items from a list of 1000, you don't have to touch all 1000 items first.

// sample :: Integer -> [a] -> [a]constsample = n => function* (xs) {
  let ys = xs.slice(0);
  let len = xs.length;
  while (n > 0 && len > 0) {
    let i = (Math.random() * len) >> 0;
    yield ys.splice(i,1)[0];
    n--; len--;
  }
}

// example inputslet items = ['a', 'b', 'c', 'd', 'e', 'f', 'g'];
let numbers = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];

// get 3 random itemsfor (let i ofsample(3) (items))
  console.log(i); // f g c// partial applicationconst lotto = sample(3);
for (let i oflotto(numbers))
  console.log(i); // 3 8 7// shuffle an arrayconstshuffle = xs => Array.from(sample (Infinity) (xs))
console.log(shuffle(items)) // [b c g f d e a]

I chose to implement sample in a way that does not mutate the input array, but you could easily argue that a mutating implementation is favourable.

For example, the shuffle function might wish to mutate the original input array. Or you might wish to sample from the same input at various times, updating the input each time.

// sample :: Integer -> [a] -> [a]constsample = n => function* (xs) {
  let len = xs.length;
  while (n > 0 && len > 0) {
    let i = (Math.random() * len) >> 0;
    yield xs.splice(i,1)[0];
    n--; len--;
  }
}

// deal :: [Card] -> [Card]constdeal = xs => Array.from(sample (2) (xs));

// setup a deck of cards (13 in this case)// cards :: [Card]let cards = 'A234567890JQK'.split('');

// deal 6 players 2 cards each// players :: [[Card]]let players = Array.from(Array(6), $=> deal(cards))

console.log(players);
// [K, J], [6, 0], [2, 8], [Q, 7], [5, 4], [9, A]// `cards` has been mutated. only 1 card remains in the deckconsole.log(cards);
// [3]

sample is no longer a pure function because of the array input mutation, but in certain circumstances (demonstrated above) it might make more sense.


Another reason I chose a generator instead of a function that just returns an array is because you may want to continue sampling until some specific condition.

Perhaps I want the first prime number from a list of 1,000,000 random numbers.

  • "How many should I sample?" – you don't have to specify
  • "Do I have to find all the primes first and then select a random prime?" – Nope.

Because we're working with a generator, this task is trivial

const randomPrimeNumber = listOfNumbers => {
  for (let x of sample(Infinity) (listOfNumbers)) {
    if (isPrime(x))
      return x;
  }
  return NaN;
}

This will continuously sample 1 random number at a time, x, check if it's prime, then return x if it is. If the list of numbers is exhausted before a prime is found, NaN is returned.

Solution 2:

Here you go. Simple code.

var random = 0, cars = ["Saab", "Volvo", "BMW"], newCars = [];

while (newCars.length < 3) {
  random = Math.floor(Math.random() * 3);
  if (newCars.indexOf(cars[random]) == -1) {
    newCars.push(cars[random]);
  }
}

console.log(newCars);

Solution 3:

Try this:

functionRandomUnique(inputArray){
  var ia = inputArray;
  if(!(ia instanceofArray)){
    thrownewError('inputArray must be an instanceof Array');
  }
  this.unique = function(){
    return ia.splice(Math.random()*ia.length, 1)[0];
  }
  this.getArray = function(){
   return ia;
  }
}
var ru = newRandomUnique(yourArray);
console.log(ru.unique());
console.log(ru.unique());

Post a Comment for "Getting Random Unique From Array"