Идиоматический способ генерации случайной буквенно-цифровой строки в Котлине
Я могу создать случайную последовательность чисел в определенном диапазоне, например:
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()
}
Затем мне придется растягивать List
с помощью
fun List<Char>.random() = this[Random().nextInt(this.size)]
Тогда я могу сделать:
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("")
}
Но может быть, лучший способ?
Ответы
Ответ 1
Предполагая, что у вас есть определенный набор исходных символов (source
в этом фрагменте), вы можете сделать это:
val source = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
java.util.Random().ints(outputStrLength, 0, source.length)
.asSequence()
.map(source::get)
.joinToString("")
Что дает строки типа "LYANFGNPNI" для outputStrLength = 10.
Два важных бита
-
Random().ints(length, minValue, maxValue)
который создает поток случайных чисел длиной от minValue до maxValue-1, и -
asSequence()
которая преобразует не очень полезный IntStream
в гораздо более полезную Sequence<Int>
.
Ответ 2
Ленивые люди просто делали
java.util.UUID.randomUUID().toString()
Вы не можете ограничить диапазон символов здесь, но я думаю, что это нормально во многих ситуациях.
Ответ 3
Начиная с Kotlin 1.3 вы можете сделать это:
fun getRandomString(length: Int) : String {
val allowedChars = "ABCDEFGHIJKLMNOPQRSTUVWXTZabcdefghiklmnopqrstuvwxyz"
return (1..length)
.map { allowedChars.random() }
.joinToString("")
}
Ответ 4
Без JDK8:
fun ClosedRange<Char>.randomString(lenght: Int) =
(1..lenght)
.map { (Random().nextInt(endInclusive.toInt() - start.toInt()) + start.toInt()).toChar() }
.joinToString("")
использование:
('a'..'z').randomString(6)
Ответ 5
('A'..'z').map { it }.shuffled().subList(0, 4).joinToString("")
Ответ 6
Использование Kotlin 1.3:
Этот метод использует ввод желаемой длины строки требуемой desiredStrLength
как целое число и возвращает случайную буквенно-цифровую строку желаемой длины строки.
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("")
}
Если вы предпочитаете неизвестную длину буквенно-цифровой (или, по крайней мере, достаточно длинную строку, например, 36
в моем примере ниже), этот метод можно использовать:
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("")
}
Ответ 7
Или используйте API-интерфейс coroutine для истинного духа Котлина:
buildSequence { val r = Random(); while(true) yield(r.nextInt(24)) }
.take(10)
.map{(it+ 65).toChar()}
.joinToString("")
Ответ 8
Основываясь на ответе Пола Хикса, я хотел использовать пользовательскую строку в качестве входных данных. В моем случае прописные и строчные буквенно-цифровые символы. Random().ints(...)
также не работал для меня, так как для его использования требовался уровень API 24 на Android.
Вот как я делаю это с абстрактным классом Kotlin Random
:
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 = "")
}
}
Процесс и то, как это работает, похож на многие другие ответы, уже размещенные здесь:
- Создайте список чисел длины
LENGTH
которые соответствуют значениям индекса строки источника, который в этом случае является ALPHA_NUMERIC
- Сопоставьте эти числа с исходной строкой, преобразовав каждый числовой индекс в символьное значение.
- Преобразуйте полученный список символов в строку, соединив их с пустой строкой в качестве символа-разделителя.
- Вернуть полученную строку.
Использовать легко, просто вызовите его как статическую функцию: IdHelper.generateId()
Ответ 9
fun randomAlphaNumericString(@IntRange(from = 1, to = 62) lenght: Int): String {
val alphaNumeric = ('a'..'z') + ('A'..'Z') + ('0'..'9')
return alphaNumeric.shuffled().take(lenght).joinToString("")
}
Ответ 10
Лучший способ, я думаю:
fun generateID(size: Int): String {
val source = "A1BCDEF4G0H8IJKLM7NOPQ3RST9UVWX52YZab1cd60ef2ghij3klmn49opq5rst6uvw7xyz8"
return (source).map { it }.shuffled().subList(0, size).joinToString("")
}
Ответ 11
Использование Collection.random()
из 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("")