Comment puis-je obtenir un nombre aléatoire dans Kotlin?

Une méthode générique qui peut renvoyer un entier aléatoire entre 2 paramètres comme le fait ruby avec rand(0..n).

Une suggestion?

58
demandé sur s1m0nw1 2017-08-15 03:49:25

15 réponses

Kotlin

Je suggère d'utiliser la fonction extension {[14] } suivante sur IntRange :

fun IntRange.random() = 
       Random().nextInt((endInclusive + 1) - start) +  start

Et utilisez-le comme ceci:

// will return an `Int` between 0 and 10 (incl.)
(0..10).random()

Si vous voulez que la fonction ne renvoie que 1, 2,..., 9 (10 exclusif), utiliser une gamme construite avec until:

(0 until 10).random()

Si vous travaillez avec JDK > 1.6, l'utilisation ThreadLocalRandom.current() au lieu de Random().

KotlinJs et autres variations

Pour kotlinjs et d'autres cas d'utilisation qui ne permettent l'utilisation de java.util.Random, voir cette alternative.

Voir Aussi cette réponse pour les variations de ma suggestion. Il comprend également une fonction d'extension pour random Char s.

Kotlin >= 1.3 multiplateforme Aléatoire

À partir de 1.3, Kotlin est livré avec son propre générateur aléatoire multiplateforme. Il est décrit dans ce GARDER. Vous pouvez maintenant faire ce qui suit (source):

Random.nextInt(0..10)

La fonction d'extension peut être simplifié à ce qui suit sur toutes les plateformes:

fun IntRange.random() = Random.nextInt(this)
179
répondu s1m0nw1 2018-09-17 06:31:09

Générer un entier aléatoire compris entre from(inclus) et to(exclusif)

import java.util.Random

val random = Random()

fun rand(from: Int, to: Int) : Int {
    return random.nextInt(to - from) + from
}
34
répondu Magnus 2017-08-15 01:07:01

À partir de Kotlin 1.2, vous pouvez écrire:

(1..3).shuffled().last()

Sachez simplement que c'est grand O (n), mais pour une petite liste (en particulier de valeurs uniques), c'est bien: D

21
répondu mutexkid 2018-02-15 22:59:11

, Vous pouvez créer un fonction d'extension semblable à java.util.Random.nextInt(int) mais celui qui prend un IntRange au lieu de Int pour son lié:

fun Random.nextInt(range: IntRange): Int {
    return range.start + nextInt(range.last - range.start)
}

Vous pouvez maintenant l'utiliser avec n'importe quel Random exemple:

val random = Random()
println(random.nextInt(5..9)) // prints 5, 6, 7, or 8

Si vous ne voulez pas avoir à gérer votre propre Random exemple, alors vous pouvez définir une méthode de convenance à l'aide, par exemple, ThreadLocalRandom.current():

fun rand(range: IntRange): Int {
    return ThreadLocalRandom.current().nextInt(range)
}

Maintenant, vous pouvez obtenir un nombre entier aléatoire comme vous le feriez dans Ruby sans avoir à déclarez vous-même une instance Random:

rand(5..9) // returns 5, 6, 7, or 8
10
répondu mfulton26 2017-08-19 23:21:03

Variation Possible de mon Autre réponse pour les caractères aléatoires

Afin d'obtenir des Charaléatoires, vous pouvez définir une fonction d'extension comme ceci

fun ClosedRange<Char>.random(): Char = 
       (Random().nextInt(endInclusive.toInt() + 1 - start.toInt()) + start.toInt()).toChar()

// will return a `Char` between A and Z (incl.)
('A'..'Z').random()

Si vous travaillez avec JDK > 1.6, l'utilisation ThreadLocalRandom.current() au lieu de Random().

Pour kotlinjs et d'autres cas d'utilisation qui ne permettent pas l'utilisation de java.util.Random, cette réponse aidera.

7
répondu s1m0nw1 2018-06-27 21:09:43

Construire hors de @s1m0nw1 {[4] } excellente réponse j'ai fait les changements suivants.

  1. (0..n) implique inclusif dans Kotlin
  2. (0 jusqu'à n) implique exclusive dans Kotlin
  3. utiliser un objet singleton pour L'instance aléatoire (facultatif)

Code:

private object RandomRangeSingleton : Random()

fun ClosedRange<Int>.random() = RandomRangeSingleton.nextInt((endInclusive + 1) - start) + start

Cas De Test:

fun testRandom() {
        Assert.assertTrue(
                (0..1000).all {
                    (0..5).contains((0..5).random())
                }
        )
        Assert.assertTrue(
                (0..1000).all {
                    (0..4).contains((0 until 5).random())
                }
        )
        Assert.assertFalse(
                (0..1000).all {
                    (0..4).contains((0..5).random())
                }
        )
    }
6
répondu Steven Spungin 2018-01-10 04:31:10

Exemples aléatoires dans la plage [1, 10]

val random1 = (0..10).shuffled().last()

Ou en utilisant Java Random

val random2 = Random().nextInt(10) + 1
4
répondu Andrey 2018-07-01 15:26:08

Si vous travaillez avec Kotlin JavaScript et n'ont pas accès à java.util.Random, ce qui suit fonctionnera:

fun IntRange.random() = (Math.random() * ((endInclusive + 1) - start) + start).toInt()

Utilisé comme ceci:

// will return an `Int` between 0 and 10 (incl.)
(0..10).random()
4
répondu s1m0nw1 2018-09-17 06:31:45

Une autre façon d'implémenter la réponse de s1m0nw1 serait d'y accéder via une variable. Ce n'est pas plus efficace mais cela vous évite d'avoir à taper ().

var ClosedRange<Int>.random: Int
    get() { return Random().nextInt((endInclusive + 1) - start) +  start }
    private set(value) {}

Et maintenant il peut être consulté en tant que tel

(1..10).random
3
répondu Quinn 2018-07-19 02:14:35

En utilisant une fonction de niveau supérieur, vous pouvez obtenir exactement la même syntaxe d'appel que dans Ruby (comme vous le souhaitez):

fun rand(s: Int, e: Int) = Random().nextInt(e + 1 - s) + s

Utilisation:

rand(1, 3) // returns either 1, 2 or 3
2
répondu Willi Mentzel 2017-12-19 08:45:11

D'abord, vous avez besoin D'un RNG. Dans Kotlin, vous devez actuellement utiliser les plates-formes spécifiques (il n'y a pas de Kotlin construit en un). Pour la JVM, c'est java.util.Random. Vous devrez en créer une instance, puis appeler random.nextInt(n).

1
répondu Mibac 2017-08-15 01:02:50

Il N'y a pas de méthode standard qui le fait mais vous pouvez facilement créer le vôtre en utilisant Math.random() ou la classe java.util.Random. Voici un exemple utilisant la méthode Math.random():

fun random(n: Int) = (Math.random() * n).toInt()
fun random(from: Int, to: Int) = (Math.random() * (to - from) + from).toInt()
fun random(pair: Pair<Int, Int>) = random(pair.first, pair.second)

fun main(args: Array<String>) {
    val n = 10

    val rand1 = random(n)
    val rand2 = random(5, n)
    val rand3 = random(5 to n)

    println(List(10) { random(n) })
    println(List(10) { random(5 to n) })
}

Ceci est un exemple de sortie:

[9, 8, 1, 7, 5, 6, 9, 8, 1, 9]
[5, 8, 9, 7, 6, 6, 8, 6, 7, 9]
1
répondu Mahdi Al-Khalaf 2017-08-15 06:19:30

Si les nombres que vous voulez choisir ne sont pas consécutifs, vous pouvez définir votre propre fonction d'extension sur la liste:

fun List<*>.randomElement() 
    = if (this.isEmpty()) null else this[Random().nextInt(this.size)]

Utilisation:

val list = listOf(3, 1, 4, 5)
val number = list.randomElement()

Renvoie l'un des nombres qui sont dans la liste.

1
répondu Willi Mentzel 2017-12-19 08:53:22

Kotlin standard lib ne fournit pas D'API de générateur de nombres aléatoires. Si vous n'êtes pas dans un projet multiplateforme, il est préférable d'utiliser l'api de plate-forme (toutes les autres réponses de la question parlent de cette solution).

Mais si vous êtes dans un contexte multiplateforme, la meilleure solution est d'implémenter random par vous-même dans Kotlin pur pour partager le même générateur de nombres aléatoires entre les plates-formes.{[8] }c'est plus simple pour dev et testing.

Pour répondre à ce problème dans mon projet personnel, j'implémente un générateur Congruentiel linéaire Kotlin pur . LCG est l'algorithme utilisé par java.util.Random. Suivez ce lien si vous voulez l'utiliser : https://gist.github.com/11e5ddb567786af0ed1ae4d7f57441d4

Mon but d'implémentation nextInt(range: IntRange) pour vous ;).

Prenez soin de mon but, LCG est bon pour la plupart des cas d'utilisation (simulation, Jeux,etc...) mais ne convient pas à une utilisation cryptographique en raison de la prévisibilité de cette méthode.

1
répondu Valentin Michalak 2018-01-11 09:54:18

Dans Kotlin 1.3 vous pouvez le faire comme

val number = Random.nextInt(limit)
0
répondu deviant 2018-09-13 14:42:21