Scala:return 一个有机会的值?

Scala: return a value with a chance?

我想对一个函数建模,该函数将 return 一组具有加权概率的值。像这样:

25% => return "a"
25% => return "b"
50% => return "c"

到目前为止我看到的大多数文档都相当沉重,并且在没有示例的情况下快速深入到科学深度,因此问题是: 实现此目标的最简单方法是什么?

编辑:我正在使用 Gatling DSL 编写带有加权操作的负载测试。内置的加权分布有一个限制(不会在循环中工作),我想通过自己的实现来避免。该代码段如下所示:

  override def scenarioBuilder = scenario(getClass.getSimpleName)
    .exec(Account.create)
    .exec(Account.login)
    .exec(Account.activate)
    .exec(Loop.create)
    .forever(getAction)

  def getAction = {
    // Here is where I lost my wits
    // 27.6% => Log.putEvents
    // 18.2% => Log.putBinary
    // 17.1% => Loop.list
    // 14.8% => Key.listIncomingRequests
    // rest => Account.get
  }

这是根据概率选择的通用函数的最短版本:

val probabilityMap = List(0.25 -> "a", 0.25 -> "b")
val otherwise = "c"

def getWithProbability[T](probs: List[(Double, T)], otherwise: T): T = {
  // some input validations:
  assert(probs.map(_._1).sum <= 1.0)
  assert(probs.map(_._1).forall(_ > 0))

  // get random in (0, 1) range
  val rand = Random.nextDouble()

  // choose by probability:
  probs.foldLeft((rand, otherwise)) {
    case ((r, _), (prob, value)) if prob > r => (1.0, value)
    case ((r, result), (prob, _)) => (r-prob, result)
  }._2
}

foldLeft 不断推进概率,直到找到 r 更小的概率;如果我们还没有找到它,我们将进入下一个概率 r-prob 到 "remove" 我们已经涵盖的范围的一部分。

EDIT:等效但可能更易于阅读的版本可以使用 scanLeft 在 [=28 之前创建 累积 范围=]对于rand已经落地的范围:

def getWithProbability[T](probs: List[(Double, T)], otherwise: T): T = {
  // same validations..

  // get random in (0, 1) range
  val rand = Random.nextDouble()

  // create cumulative values, in this case (0.25, a), (0,5, b)
  val ranges = probs.tail.scanLeft(probs.head) {
    case ((prob1, _), (prob2, value)) => (prob1+prob2, value)
  }
  ranges.dropWhile(_._1 < rand).map(_._2).headOption.getOrElse(otherwise)
}

那里,干净且准备就绪:

randomSwitchOrElse(
    27.6 -> exec(Log.putEvents),
    18.2 -> exec(Log.putBinary))