【发布时间】:2017-12-16 21:33:22
【问题描述】:
如何以简单明了的方式从列表中获取随机项。
例如:如果我想从这个列表中得到一个偶数随机数。
val list = listOf(1, 2, 3, 4, 5, 6, 7, 9).filter { it % 2 == 0 }
注意:
我知道在 java 中有一些类似的答案可以解决这个问题,但我认为我们可以在 kotlin 中有更简洁的方式。
【问题讨论】:
如何以简单明了的方式从列表中获取随机项。
例如:如果我想从这个列表中得到一个偶数随机数。
val list = listOf(1, 2, 3, 4, 5, 6, 7, 9).filter { it % 2 == 0 }
注意:
我知道在 java 中有一些类似的答案可以解决这个问题,但我认为我们可以在 kotlin 中有更简洁的方式。
【问题讨论】:
Kotlin 1.3 现在可用于多平台随机数生成器! 你可以这样使用它:
import kotlin.random.Random
fun main() {
println(Random.nextBoolean())
println(Random.nextInt())
}
或者在你的情况下
fun main() {
val list = (1..9).filter { it % 2 == 0 }
println(list.random())
}
从 Kotlin 1.2 开始,我们有了 Iterable.shuffled()。此方法可以帮助您使用List.take() 来提取您想要的元素数量(本例中只有一个)。
val list = (1..9).filter { it % 2 == 0 }
return list.shuffled().take(1)[0]
此方法不如 1.2 之前的优化,但它适用于多平台上下文。根据您的上下文使用您需要的那个。
在 Kotlin 1.2 之前,多平台上下文中不存在生成随机数的解决方案。最简单的解决方案是直接调用 Platform Random。
在 JVM 上,如果我们使用 JDK > 1.6,我们使用 Random 甚至 ThreadLocalRandom。
import java.util.Random
fun IntRange.random() = Random().nextInt((endInclusive + 1) - start) + start
在 JS 上,我们使用Math.Random。
fun IntRange.random() = (Math.random() * ((endInclusive + 1) - start) + start).toInt()
【讨论】:
我认为最简单和最简洁的方法是创建返回随机元素的扩展函数,以便可以这样使用:
val random = list.random()
扩展功能:
/**
* Returns a random element.
*/
fun <E> List<E>.random(): E? = if (size > 0) get(Random().nextInt(size)) else null
感谢@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
【讨论】:
Random 实例。通常随机性需要几次调用才能调整到可接受的阈值。
Random() 的当前实现是:public Random() { this(seedUniquifier() ^ System.nanoTime());} @FrancescoMenzani,您对新初始化的实例有什么顾虑?
为了得到一个随机数而对整个列表进行打乱是浪费性能。
使用 random() 代替 Kotin 1.3 中引入的
val randomNumber = listOf(1, 6, 8).random()
对于您的特殊用例,首先过滤列表并从剩余项目中选择一个随机数是有意义的。
val randomEvenNumber = listOf(1, 2, 3, 4, 5, 6, 7, 9).filter { it % 2 == 0 }.random()
【讨论】:
正如其他人所说,list.random() 现在应该可以解决问题,但如果您不知道列表是否为空,.random() 可能会引发异常。除了将.randomOrNull() 实现为扩展函数之外,您还可以使用list.shuffled().firstOrNull() 破解它,但要注意这对于长列表来说很慢。
.randomOrNull() 方法:
fun <E> List<E>.randomOrNull(): E? = if (size > 0) random() else null
【讨论】:
如果你想要一个列表中的 25 个随机元素,我会这样做:
var suliTraffic = ArrayList<SuliTraffic>()
var randomsuliTraffic = ArrayList<SuliTraffic>()
// I have add some data to my Array List
randomsuliTraffic.add(new)
// Here i shuffle all the information i have wich is over 400 object
randomsuliTraffic.shuffle()
// now you can just simply get 25 item from this randomsuliTraffic like this
for (i in randomsuliTraffic.take(25)){
suliTraffic.add(i)
}
现在您可以在suliTraffic 列表中找到 25 个随机元素。
【讨论】: