web-dev-qa-db-fra.com

Moyen idiomatique de générer une chaîne alphanumérique aléatoire en Kotlin

Je peux générer une séquence aléatoire de nombres dans une certaine plage, comme suit:

fun ClosedRange<Int>.random() = Random().nextInt(endInclusive - start) +  start
fun generateRandomNumberList(len: Int, low: Int = 0, high: Int = 255): List<Int> {
  (0..len-1).map {
    (low..high).random()
  }.toList()
}

Ensuite, je vais devoir étendre List avec:

fun List<Char>.random() = this[Random().nextInt(this.size)]

Alors je peux faire:

fun generateRandomString(len: Int = 15): String{
  val alphanumerics = CharArray(26) { it -> (it + 97).toChar() }.toSet()
      .union(CharArray(9) { it -> (it + 48).toChar() }.toSet())
  return (0..len-1).map {
      alphanumerics.toList().random()
  }.joinToString("")
}

Mais peut-être qu'il y a un meilleur moyen?

18
breezymri

En supposant que vous ayez un ensemble spécifique de caractères source (source dans cet extrait de code), vous pouvez procéder comme suit:

val source = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
Java.util.Random().ints(outputStrLength, 0, source.length)
        .asSequence()
        .map(source::get)
        .joinToString("")

Ce qui donne des chaînes comme "LYANFGNPNI" pour outputStrLength = 10.

Les deux bits importants sont

  1. Random().ints(length, minValue, maxValue) qui produit un flux de length nombres aléatoires chacun de minValue à maxValue-1
  2. asSequence() qui convertit la IntStream peu utile en un Sequence<Int> beaucoup plus utile.
22
Paul Hicks

Les gens paresseux feraient juste

Java.util.UUID.randomUUID().toString()

Vous ne pouvez pas restreindre la plage de caractères ici, mais je suppose que cela convient dans de nombreuses situations.

15
Holger Brandl

Sans JDK8:

fun ClosedRange<Char>.randomString(lenght: Int) = 
    (1..lenght)
        .map { (Random().nextInt(endInclusive.toInt() - start.toInt()) + start.toInt()).toChar() }
        .joinToString("")

usage:

('a'..'z').randomString(6)
8

Ou utilisez la coroutine API pour le véritable esprit Kotlin:

buildSequence { val r = Random(); while(true) yield(r.nextInt(24)) }
   .take(10)
   .map{(it+ 65).toChar()}
   .joinToString("")
2
Holger Brandl

Depuis Kotlin 1.3 vous pouvez le faire:

fun getRandomString(length: Int) : String {
    val allowedChars = "ABCDEFGHIJKLMNOPQRSTUVWXTZabcdefghiklmnopqrstuvwxyz"
    return (1..length)
        .map { allowedChars.random() }
        .joinToString("")
}
2
WhiteAngel

Utiliser Kotlin 1.3 :

Cette méthode utilise une entrée de la longueur de chaîne désirée desiredStrLength sous forme d’entier et renvoie une chaîne alphanumérique aléatoire de la longueur de chaîne souhaitée.

fun randomAlphaNumericString(desiredStrLength: Int): String {
    val charPool: List<Char> = ('a'..'z') + ('A'..'Z') + ('0'..'9')

    return (1..desiredStrLength)
        .map{ kotlin.random.Random.nextInt(0, charPool.size) }
        .map(charPool::get)
        .joinToString("")
}

Si vous préférez une longueur alphanumérique inconnue (ou au moins une longueur de chaîne assez longue comme 36 dans l'exemple ci-dessous), cette méthode peut être utilisée:

fun randomAlphanumericString(): String {
    val charPool: List<Char> = ('a'..'z') + ('A'..'Z') + ('0'..'9')
    val outputStrLength = (1..36).shuffled().first()

    return (1..outputStrLength)
        .map{ kotlin.random.Random.nextInt(0, charPool.size) }
        .map(charPool::get)
        .joinToString("")
}
1
jojo

En me basant sur la réponse de Paul Hicks, je voulais une chaîne personnalisée en entrée. Dans mon cas, les caractères alphanumériques majuscules et minuscules. Random().ints(...) ne fonctionnait pas non plus pour moi, car il fallait un niveau de 24 API sur Android pour l'utiliser.

Voici comment je le fais avec la classe abstraite Random de Kotlin:

import kotlin.random.Random

object IdHelper {

    private val ALPHA_NUMERIC = ('0'..'9') + ('A'..'Z') + ('a'..'z')
    private const val LENGTH = 20

    fun generateId(): String {
        return List(LENGTH) { Random.nextInt(0, ALPHA_NUMERIC.size) }
                .map { ALPHA_NUMERIC[it] }
                .joinToString(separator = "")
    }
}

Le processus et son fonctionnement sont similaires à beaucoup d'autres réponses déjà publiées ici:

  1. Génère une liste de nombres de longueur LENGTH qui correspondent aux valeurs d'index de la chaîne source, qui dans ce cas est ALPHA_NUMERIC
  2. Mappez ces nombres sur la chaîne source, en convertissant chaque index numérique en valeur de caractère
  3. Convertissez la liste résultante de caractères en une chaîne en les joignant à la chaîne vide en tant que caractère séparateur.
  4. Renvoie la chaîne résultante.

Son utilisation est facile, appelez-la comme une fonction statique: IdHelper.generateId()

1
Kyle Falconer
('A'..'z').map { it }.shuffled().subList(0, 4).joinToString("")
1
Louis Saglio
fun randomAlphaNumericString(@IntRange(from = 1, to = 62) lenght: Int): String {
    val alphaNumeric = ('a'..'z') + ('A'..'Z') + ('0'..'9')
    return alphaNumeric.shuffled().take(lenght).joinToString("")
}
0
Sefa Gürel

La meilleure façon que je pense:

fun generateID(size: Int): String {
    val source = "A1BCDEF4G0H8IJKLM7NOPQ3RST9UVWX52YZab1cd60ef2ghij3klmn49opq5rst6uvw7xyz8"
    return (source).map { it }.shuffled().subList(0, size).joinToString("")
}
0
Mickael Belhassen