0

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

var random = Math.floor(Math.random() * (3 - 1 + 1)) + 1;

var cars = ["Saab", "Volvo", "BMW"];
for ( var i = 0,l = cars.length; i <random; i++ ) {
   var item = cars[Math.floor(Math.random()*cars.length)];
   console.log(item);
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
halfer
  • 19,824
  • 17
  • 99
  • 186
Mona Coder
  • 6,212
  • 18
  • 66
  • 128
  • 3
    shuffle the array, then pop them off – Jaromanda X Oct 12 '16 at 22:05
  • how many items do you want returned ? – jack blank Oct 12 '16 at 22:21
  • This has been asked many times before in all kinds of variations. Please have a look at https://www.google.com/search?q=unique+random+values+array+javascript+site:stackoverflow.com – trincot Oct 12 '16 at 22:28
  • `function randommInt(min, max){ return Math.floor(Math.random() * (max - min + 1) + min) } var cars = ["Saab", "Volvo", "BMW"]; console.log(cars[randommInt(0, cars.length- 1)])` – jack blank Oct 12 '16 at 22:28

3 Answers3

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]
const sample = 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 inputs
let items = ['a', 'b', 'c', 'd', 'e', 'f', 'g'];
let numbers = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];

// get 3 random items
for (let i of sample(3) (items))
  console.log(i); // f g c

// partial application
const lotto = sample(3);
for (let i of lotto(numbers))
  console.log(i); // 3 8 7

// shuffle an array
const shuffle = 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]
const sample = 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]
const deal = 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 deck
console.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.

Mulan
  • 129,518
  • 31
  • 228
  • 259
0

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);
kind user
  • 40,029
  • 7
  • 67
  • 77
-1

Try this:

function RandomUnique(inputArray){
  var ia = inputArray;
  if(!(ia instanceof Array)){
    throw new Error('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 = new RandomUnique(yourArray);
console.log(ru.unique());
console.log(ru.unique());
StackSlave
  • 10,613
  • 2
  • 18
  • 35