使用kotlin流从列表中获取随机项目

hum*_*zed 21 random kotlin

如何以简单明了的方式从列表中获取随机项.
例如:如果我想从这个列表中得到一个偶数随机数.

val list = listOf(1, 2, 3, 4, 5, 6, 7, 9).filter { it % 2 == 0 }
Run Code Online (Sandbox Code Playgroud)

注意:
我知道java中有一些类似的答案可以解决这个问题,但我认为我们可以在kotlin中使用更简洁的方法.

Val*_*lak 24

从Kotlin 1.2开始,我们就有了Iterable.shuffled().此方法可以帮助您使用List.take()提取所需的元素数量(在此示例中只有一个).

val list = (1..9).filter { it % 2 == 0 }
return list.shuffled().take(1)[0]
Run Code Online (Sandbox Code Playgroud)

这种方法不如Humazed方法优化,但它可以在多平台上下文中工作,并且更灵活.


编辑:

Random计划为Kotlin 1.3-M1标准库提供一个对象,有关此内容的更多信息:https://github.com/Kotlin/KEEP/blob/random/proposals/stdlib/random.md


编辑2:

现在可以在Kotlin 1.3-M1的预览版中使用多平台随机数发生器.有关这方面的更多信息:https://blog.jetbrains.com/kotlin/2018/07/see-whats-coming-in-kotlin-1-3-m1/


编辑3:

Kotlin 1.3现在可用于Multiplatform随机数发生器! 你可以像这样使用它:

import kotlin.random.Random

fun main() {
    println(Random.nextBoolean())
    println(Random.nextInt())
}
Run Code Online (Sandbox Code Playgroud)

在线尝试!

或者在你的情况下

fun main() {
    val list = (1..9).filter { it % 2 == 0 }
    println(list.random())
}
Run Code Online (Sandbox Code Playgroud)

在线尝试!

  • 我正在使用这种方法,但我需要对外部效率低下的整个列表进行洗牌。当你想要的只是获得一个随机元素时。 (2认同)
  • 为什么不"list.shuffled()[0]" (2认同)

hum*_*zed 17

我认为最简单,最简洁的方法是创建一个返回随机元素的扩展函数,以便可以这样使用:

val random = list.random()
Run Code Online (Sandbox Code Playgroud)

扩展功能:

/**
 * Returns a random element.
 */
fun <E> List<E>.random(): E? = if (size > 0) get(Random().nextInt(size)) else null
Run Code Online (Sandbox Code Playgroud)

感谢@Francesco评论这里是另一个函数,它将Random实例作为随机源

/**
 * Returns a random element using the specified [random] instance as the source of randomness.
 */
fun <E> List<E>.random(random: java.util.Random): E? = if (size > 0) get(random.nextInt(size)) else null
Run Code Online (Sandbox Code Playgroud)

  • 注意每次都使用新初始化的 `Random` 实例。通常随机性需要几次调用才能调整到可接受的阈值。 (2认同)
  • `Random()`的当前实现是:`public Random(){this(seedUniquifier()^ System.nanoTime());}`@FrancescoMenzani,你对新初始化的实例有什么关注? (2认同)

Wil*_*zel 10

仅仅为了获得一个随机数而对整个列表进行混洗是浪费性能的。

使用random()Kotin 1.3中引入的替代方法

val randomNumber = listOf(1, 6, 8).random()
Run Code Online (Sandbox Code Playgroud)

对于您的特殊用例,首先过滤列表并从其余项中选择一个随机数将是有意义的。

val randomEvenNumber = listOf(1, 2, 3, 4, 5, 6, 7, 9).filter { it % 2 == 0 }.random()
Run Code Online (Sandbox Code Playgroud)


归档时间:

查看次数:

11530 次

最近记录:

6 年,2 月 前