Idiomatische manier om een ​​willekeurige alfanumerieke tekenreeks in Kotlin te genereren

Ik kan een willekeurige reeks getallen in een bepaald bereik als volgt genereren:

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()
}

Dan moet ik Listuitbreiden met:

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

Dan kan ik het volgende doen:

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("")
}

Maar misschien is er een betere manier?


Antwoord 1, autoriteit 100%

Sinds Kotlin 1.3kun je dit doen:

fun getRandomString(length: Int) : String {
    val allowedChars = ('A'..'Z') + ('a'..'z') + ('0'..'9')
    return (1..length)
        .map { allowedChars.random() }
        .joinToString("")
}

Antwoord 2, autoriteit 52%

Luie mensen zouden het gewoon doen

java.util.UUID.randomUUID().toString()

Je kunt het tekenbereik hier niet beperken, maar ik denk dat het in veel situaties sowieso prima is.


Antwoord 3, autoriteit 32%

Ervan uitgaande dat u een specifieke set brontekens heeft (sourcein dit fragment), kunt u dit doen:

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

Dat geeft strings zoals “LYANFGNPNI” voor outputStrLength = 10.

De twee belangrijke stukjes zijn

  1. Random().ints(length, minValue, maxValue)die een stroom van lengthwillekeurige getallen produceert, elk van minValuetot maxValue-1, en
  2. asSequence()die de niet-massaal bruikbare IntStreamomzet in een veel bruikbare Sequence<Int>.

Antwoord 4, autoriteit 19%

Met behulp van Collection.random()van Kotlin 1.3:

// Descriptive alphabet using three CharRange objects, concatenated
val alphabet: List<Char> = ('a'..'z') + ('A'..'Z') + ('0'..'9')
// Build list from 20 random samples from the alphabet,
// and convert it to a string using "" as element separator
val randomString: String = List(20) { alphabet.random() }.joinToString("")

Antwoord 5, autoriteit 10%

Zonder JDK8:

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

gebruik:

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

Antwoord 6, autoriteit 8%

Om het te definiëren voor een gedefinieerde lengte:

val randomString = UUID.randomUUID().toString().substring(0,15)

waar 15het aantal tekens is


Antwoord 7, autoriteit 5%

('A'..'z').map { it }.shuffled().subList(0, 4).joinToString("")

Antwoord 8, autoriteit 4%

Met Kotlin 1.3:

Deze methode gebruikt een invoer van de gewenste tekenreekslengte desiredStrLengthals een geheel getal en retourneert een willekeurige alfanumerieke tekenreeks van de gewenste tekenreekslengte.

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("")
}

Als u de voorkeur geeft aan een onbekende lengte van alfanumeriek (of op zijn minst een behoorlijk lange tekenreekslengte zoals 36in mijn voorbeeld hieronder), kan deze methode worden gebruikt:

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("")
}

Antwoord 9, autoriteit 3%

Of gebruik de coroutine-API voor de echte Kotlin-geest:

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

Antwoord 10, autoriteit 2%

Voortbouwend op het antwoord van Paul Hicks, wilde ik een aangepaste string als invoer. In mijn geval alfanumerieke tekens in hoofdletters en kleine letters. Random().ints(...)werkte ook niet voor mij, omdat het een API-niveau van 24 op Android vereiste om het te gebruiken.

Dit is hoe ik het doe met Kotlin’s Randomabstracte klasse:

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 = "")
    }
}

Het proces en hoe dit werkt, is vergelijkbaar met veel van de andere antwoorden die hier al zijn gepost:

  1. Genereer een lijst met getallen met de lengte LENGTHdie overeenkomen met de indexwaarden van de brontekenreeks, in dit geval ALPHA_NUMERIC
  2. Wijs die getallen toe aan de bronreeks, waarbij elke numerieke index wordt omgezet in de tekenwaarde
  3. Converteer de resulterende lijst met tekens naar een tekenreeks en voeg ze samen met de lege tekenreeks als scheidingsteken.
  4. Retourneer de resulterende tekenreeks.

Gebruik is eenvoudig, noem het gewoon een statische functie: IdHelper.generateId()


Antwoord 11, autoriteit 2%

Ik gebruik de volgende code om willekeurige woorden en zinnen te genereren.

val alphabet: List<Char> = ('a'..'z') + ('A'..'Z') + ('0'..'9')
val randomWord: String = List((1..10).random()) { alphabet.random() }.joinToString("")
val randomSentence: String = (1..(1..10).random()).joinToString(" ") { List((1..10).random()) { alphabet.random() }.joinToString("") }

Antwoord 12

fun randomAlphaNumericString(@IntRange(from = 1, to = 62) lenght: Int): String {
    val alphaNumeric = ('a'..'z') + ('A'..'Z') + ('0'..'9')
    return alphaNumeric.shuffled().take(lenght).joinToString("")
}

Antwoord 13

De beste manier waarop ik denk:

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

Antwoord 14

de vraag is al oud, maar ik denk dat een andere geweldige oplossing (zou moeten werken sinds Kotlin 1.3) de volgende zou zijn:

// Just a simpler way to create a List of characters, as seen in other answers
// You can achieve the same effect by declaring it as a String "ABCDEFG...56789"
val alphanumeric = ('A'..'Z') + ('a'..'z') + ('0'..'9')
fun generateAlphanumericString(length: Int) : String {
    // The buildString function will create a StringBuilder
    return buildString {
        // We will repeat length times and will append a random character each time
        // This roughly matches how you would do it in plain Java
        repeat(length) { append(alphanumeric.random()) }
    }
}

Antwoord 15

U kunt RandomStringUtils.randomAlphanumeric(min: Int, max: Int) -> Stringvan apache-commons-lang3


Antwoord 16

Hier is een cryptografisch beveiligde versie ervan, althans dat geloof ik:

fun randomString(len: Int): String {
    val random = SecureRandom()
    val chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789".toCharArray()
    return (1..len).map { chars[random.nextInt(chars.size)] }.joinToString("")
}

Other episodes