1

Scala のリストから n 個の要素のサブセットをランダムにサンプリングする必要があります。n 個の要素のそれぞれが一意であることを手動でチェックすることなく、これを行う便利な方法があるかどうか疑問に思っていました。現時点では、次のようなものがあります。

import util.Random

def sample(itms:List[A], sampleSize:Int) {
  var numbersSeen = Set[Int]()
  var sampled = List[A]()
  val itmLen = itms.size()
  var sampleIdex = Random.nextInt(itmLen)
  while(sampled < sampleSize) {
    if(numbersSeen.contains(sampleIdex)){
      sampleIdex = Random.nextInt(itmLen)
    } else {
      numbersSeen.add(sampleIdex)
      sampled.add(itms(sampleIdex))
    }
  }
  sampled
}

範囲内の整数の非反復ランダムリストを生成するか、リストから n 要素をランダムにサンプリングするために実行できる、よりエレガントな何かがあることを望んでいました。

4

5 に答える 5

5

リストが長すぎない場合は、インデックス番号のリストをシャッフルしてから、そのリストを行進できます。

Scala では、次のようになります。

val aList = ('A' to 'Z').toList

val aListIterator = scala.util.Random.shuffle((0 until aList.length).toList).toIterator

そして、ループ構造で:

...
if( aListIterator.hasNext ) aList(aListIterator.next)
...

リストが巨大な場合は、リスト サイズの範囲内で一意の乱数を返す関数 (インデックスとして使用) を使用する方が適切な場合があります。Jeff Preshing は最近、一意の乱数についてブログを書いています ( http://preshing.com/20121224/how-to-generate-a-sequence-of-unique-random-integers ) 。

于 2013-02-14T00:03:13.890 に答える
3

ランダムに 1 つを選択し、単純なサイズ-1 (末尾) で再帰的に、選択したものを除いてリストからサンプリングできます。

    def sample[A](itms:List[A], sampleSize:Int) = {

        def collect(vect: Vector[A], sampleSize: Int, acc : List[A]) : List[A] = {
            if (sampleSize == 0) acc
            else {
                val index = Random.nextInt(vect.size)
                collect( vect.updated(index, vect(0)) tail, sampleSize - 1, vect(index) :: acc)
            }
        }

        collect(itms toVector, sampleSize, Nil)
    }                                 //> sample: [A](itms: List[A], sampleSize: Int)List[A]


    sample(1 to 10 toList, 5)         //> res0: List[Int] = List(6, 8, 2, 1, 10)
于 2013-02-13T21:51:43.890 に答える
1
itms.map(x => (x, util.Random.nextDouble)).sortBy(_._2).take(sampleSize).map(_._1)

並べ替えの非効率性を気にしない限り。

于 2013-02-13T21:24:20.617 に答える
0

サブセットのセットからランダムなサンプルを取得できます。つまり、次のようになります。

val distinctSubsets = itms.to[Set].subsets(sampleSize)

次に、それらのいずれかをランダムに選択します。

于 2013-02-13T21:02:46.723 に答える
-1

このアプローチはどうですか?

trait RandomOrdering[T] extends Ordering[T]

object RandomOrdering {
  implicit def defaultOrdering[T] = new RandomOrdering[T] {
    def compare(x:T, y:T) = (Random nextInt 3) - 1
  }
}

def sample[A](items:List[A], sampleSize:Int)(implicit r:RandomOrdering[A]) =
  items.sorted take sampleSize

パフォーマンスが低下する可能性がありますが、別の を注入することもできますRandomOrdering

于 2013-02-13T21:11:58.853 に答える