How to ensure that same random element is not selected twice

I'm using below code to randomly select two elements :

scala.util.Random.shuffle(myList).take(2)

How can I ensure that the two elements are not selected twice ?

Could I remove the random element from the List, create a new list and then use the same code as above ?

Answers


A bit more context would be nice; as in, why are you not converting your list to something easier to handle for this task, like an iterator or array?

Keeping it as a list, I see two options:

  1. Use the length of the list to pick two random numbers from an array of indices, check that the two random numbers aren't the same and then pull those from the list.
  2. Take 1, remove it, then take another instead of taking two at once.

It would be enough to shuffle it once. However, if you want non-duplicates, your list must not contain duplicate entries.

import scala.util.Random

object shuffleList {
  val l = (1 to 13).toList //=> List(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13)

  // shuffle once
  val shuf = Random.shuffle(l) //=> List(13, 11, 3, 5, 2, 7, 6, 9, 4, 10, 12, 1, 8)

  // iterate them grouped by interval of 2
  shuf.grouped(2).foreach(println)
                         // => List(13, 11)
                                              //| List(3, 5)
                                              //| List(2, 7)
                                              //| List(6, 9)
                                              //| List(4, 10)
                                              //| List(12, 1)
                                              //| List(8)
}

When the original list has duplicates:

val dl = List(1, 2, 2, 3, 4, 5, 5, 6, 7, 8, 9, 10, 11, 11, 12, 13)
                                                  //> dl  : List[Int] = List(1, 2, 2, 3, 4, 5, 5, 6, 7, 8, 9, 10, 11, 11, 12, 13)


  Random.shuffle(dl.toSet.toList).grouped(2).foreach(println)
                                                  //> List(7, 3)
                                                  //| List(1, 11)
                                                  //| List(13, 8)
                                                  //| List(6, 5)
                                                  //| List(10, 4)
                                                  //| List(12, 9)
                                                  //| List(2)

The safest and easiest way is convert it to Set which contains unique elements

scala> val myList = List(1,2,3,3,3,3,1,1,1,1,4,4,4,5,5,5,6,7,7,7,8) 
myList: List[Int] = List(1, 2, 3, 3, 3, 3, 1, 1, 1, 1, 4, 4, 4, 5, 5, 5, 6, 7, 7, 7, 8)

scala> scala.util.Random.shuffle(myList.toSet).take(2)
res1: scala.collection.immutable.Set[Int] = Set(5, 1)

this will ensure that only unique elements will be taken


Consider defining an iterator over the shuffled list,

class RandList[A] (list: List[A]) {

    val idx = scala.util.Random.shuffle(list)
    val it = idx.iterator

    def next() = if (it.hasNext) Some(it.next) else None

    def getPair() = (next(), next())
}

This approach avoids removing elements and hence updating the list at each call.

Then for example,

scala> val a = new RandList(List(1,2,3))
a: RandList[Int] = RandList@7eee8f

scala> a.getPair()
res25: (Option[Int], Option[Int]) = (Some(1),Some(3))

scala> a.getPair()
res26: (Option[Int], Option[Int]) = (Some(2),None)

On the other hand, in order to remove duplicates from a list consider either myList.distinct or myList.toSet.toList.


If your list have unique elements, it's not possible to take the same element twice by definition:

class List in scala

"Returns the n first elements of this list, or else the whole list, if it has less than n elements."


Need Your Help

Getting KnockoutJS Validation working with Bootstrap Popover

javascript twitter-bootstrap knockout.js popover

Almost there, just need the popover to appear only after submit button is clicked and the field has an alert class added to it.