Hasilkan string alfanumerik acak di Swift

208

Bagaimana saya bisa menghasilkan string alfanumerik acak di Swift?

Wisnu
sumber

Jawaban:

355

Swift 4.2 Update

Swift 4.2 memperkenalkan peningkatan besar dalam berurusan dengan nilai dan elemen acak. Anda dapat membaca lebih lanjut tentang peningkatan tersebut di sini . Berikut ini metode yang direduksi menjadi beberapa baris:

func randomString(length: Int) -> String {
  let letters = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
  return String((0..<length).map{ _ in letters.randomElement()! })
}

Pembaruan Swift 3.0

func randomString(length: Int) -> String {

    let letters : NSString = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
    let len = UInt32(letters.length)

    var randomString = ""

    for _ in 0 ..< length {
        let rand = arc4random_uniform(len)
        var nextChar = letters.character(at: Int(rand))
        randomString += NSString(characters: &nextChar, length: 1) as String
    }

    return randomString
}

Jawaban asli:

func randomStringWithLength (len : Int) -> NSString {

    let letters : NSString = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"

    var randomString : NSMutableString = NSMutableString(capacity: len)

    for (var i=0; i < len; i++){
        var length = UInt32 (letters.length)
        var rand = arc4random_uniform(length)
        randomString.appendFormat("%C", letters.characterAtIndex(Int(rand)))
    }

    return randomString
}
iAhmed
sumber
1
Apakah ada cara saya dapat memodifikasi di atas untuk memastikan bahwa string alfanumerik yang dihasilkan hanya sepanjang 6 atau 8 karakter?
ksa_coder
4
randomString (panjang: 6) atau randomString (panjang: 8)
Simon H
58

Inilah solusi yang siap digunakan dalam sintaks Swiftier . Anda cukup menyalin dan menempelkannya:

func randomAlphaNumericString(length: Int) -> String {
    let allowedChars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
    let allowedCharsCount = UInt32(allowedChars.characters.count)
    var randomString = ""

    for _ in 0..<length {
        let randomNum = Int(arc4random_uniform(allowedCharsCount))
        let randomIndex = allowedChars.index(allowedChars.startIndex, offsetBy: randomNum)
        let newCharacter = allowedChars[randomIndex]
        randomString += String(newCharacter)
    }

    return randomString
}

Jika Anda lebih suka Kerangka yang juga memiliki beberapa fitur yang lebih berguna maka jangan ragu untuk checkout proyek saya HandySwift . Ini juga termasuk solusi yang bagus untuk string alfanumerik acak :

String(randomWithLength: 8, allowedCharactersType: .alphaNumeric) // => "2TgM5sUG"
Astaga
sumber
49

Anda dapat menggunakannya juga dengan cara berikut:

extension String {

    static func random(length: Int = 20) -> String {

        let base = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
        var randomString: String = ""

        for _ in 0..<length {

            let randomValue = arc4random_uniform(UInt32(base.characters.count))
            randomString += "\(base[base.startIndex.advancedBy(Int(randomValue))])"
        }

        return randomString
    }
}

Penggunaan sederhana:

let randomString = String.random()

Sintaks Swift 3:

extension String {

    static func random(length: Int = 20) -> String {
        let base = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
        var randomString: String = ""

        for _ in 0..<length {
            let randomValue = arc4random_uniform(UInt32(base.characters.count))
            randomString += "\(base[base.index(base.startIndex, offsetBy: Int(randomValue))])"
        }
        return randomString
    }
}

Sintaks Swift 4:

extension String {

    static func random(length: Int = 20) -> String {
        let base = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
        var randomString: String = ""

        for _ in 0..<length {
            let randomValue = arc4random_uniform(UInt32(base.count))
            randomString += "\(base[base.index(base.startIndex, offsetBy: Int(randomValue))])"
        }
        return randomString
    }
}
Bartłomiej Semańczyk
sumber
29

Cepat:

let randomString = NSUUID().uuidString
Kata
sumber
UUID (). UuidString sekarang
Mark Bridges
2
UUID terkadang memberikan string yang sama!
Burak Öztürk
2
Ada berbagai jenis UUID, beberapa di antaranya berdasarkan waktu. Yang digunakan di Swift Foundation adalah V4, acak . Ada sangat sedikit peluang (seperti, sangat kecil bahwa UUID yang sama akan dihasilkan dua kali.
Robin Daugherty
11

Dengan Swift 4.2, taruhan terbaik Anda adalah membuat string dengan karakter yang Anda inginkan dan kemudian menggunakan randomElement untuk memilih setiap karakter:

let length = 32
let characters = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
let randomCharacters = (0..<length).map{_ in characters.randomElement()!}
let randomString = String(randomCharacters)

Saya lebih detail tentang perubahan ini di sini .

leogdion
sumber
3
Alih-alih peta Anda dapat menggunakan compactMap dan kemudian tidak perlu! operator. ;)
Kristaps Grinbergs
1
Hey @KristapsGrinbergs! Pikir saya adalah bahwa membuka paksa akan memiliki kinerja yang lebih baik daripada menggunakan compactMap.
leogdion
11

DIPERBARUI 2019.

Dalam kasus yang tidak biasa itu

masalah kinerja.

Berikut adalah fungsi yang sangat jelas yang menyimpan :

func randomNameString(length: Int = 7)->String{
    
    enum s {
        static let c = Array("abcdefghjklmnpqrstuvwxyz12345789")
        static let k = UInt32(c.count)
    }
    
    var result = [Character](repeating: "-", count: length)
    
    for i in 0..<length {
        let r = Int(arc4random_uniform(s.k))
        result[i] = s.c[r]
    }
    
    return String(result)
}

Ini untuk saat Anda memiliki set karakter yang telah diperbaiki .

Tip berguna:

Perhatikan bahwa "abcdefghjklmnpqrstuvwxyz12345789" menghindari karakter 'buruk'

Tidak ada 0, o, O, i, dll ... karakter yang sering membingungkan manusia.

Ini sering dilakukan untuk kode pemesanan dan kode serupa yang akan digunakan pelanggan manusia.

Fattie
sumber
1
Upvoting untuk repeating:count:.
Cœur
10

Sederhana dan Cepat - UUID (). UuidString

// Mengembalikan string yang dibuat dari UUID, seperti "E621E1F8-C36C-495A-93FC-0C247A3E6E5F"

public uarString: String {get}

https://developer.apple.com/documentation/foundation/uuid

Swift 3.0

let randomString = UUID().uuidString //0548CD07-7E2B-412B-AD69-5B2364644433
print(randomString.replacingOccurrences(of: "-", with: ""))
//0548CD077E2B412BAD695B2364644433

EDIT

Tolong jangan bingung dengan UIDevice.current.identifierForVendor?.uuidStringitu tidak akan memberikan nilai acak.

Mohamed Jaleel Nazir
sumber
6

Versi Swift 2.2

// based on https://gist.github.com/samuel-mellert/20b3c99dec168255a046
// which is based on https://gist.github.com/szhernovoy/276e69eb90a0de84dd90
// Updated to work on Swift 2.2

func randomString(length: Int) -> String {
    let charactersString = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
    let charactersArray : [Character] = Array(charactersString.characters)

    var string = ""
    for _ in 0..<length {
        string.append(charactersArray[Int(arc4random()) % charactersArray.count])
    }

    return string
}

Pada dasarnya panggil metode ini yang akan menghasilkan string acak panjang bilangan bulat yang diserahkan ke fungsi. Untuk mengubah karakter yang mungkin, cukup edit string karakterString. Mendukung karakter unicode juga.

https://gist.github.com/gingofthesouth/54bea667b28a815b2fe33a4da986e327

Ernest Cunningham
sumber
2
Untuk beberapa alasan yang disayangkan, versi ini terkadang memberikanEXC_BAD_INSTRUCTION
Joe
Hai Joe, apakah Anda memiliki kode demo yang dapat mereproduksi kesalahan ini?
Ernest Cunningham
Biarkan saya melihat apa yang bisa saya lakukan; Saya hanya menyebutnya apa adanya di outlet tindakan IB dengan let random = randomString(16). EXC hanya di perangkat nyata dan saya tidak melihatnya di simulator dan itu terputus-putus di perangkat.
Joe
1
Lihat pertanyaan SO ini untuk alasan mengapa ini lumpuh separuh waktu pada perangkat 32-bit: stackoverflow.com/questions/25274265/…
julien_c
Penting: random % count tidak tidak (selalu) membuat distribusi seragam. Jika ini relevan bagi Anda, lihat jawaban lain yang digunakan arc4random_uniform().
Raphael
6

Untuk orang-orang yang tidak ingin mengetikkan seluruh rangkaian karakter:

func randomAlphanumericString(length: Int) -> String  {
    enum Statics {
        static let scalars = [UnicodeScalar("a").value...UnicodeScalar("z").value,
                              UnicodeScalar("A").value...UnicodeScalar("Z").value,
                              UnicodeScalar("0").value...UnicodeScalar("9").value].joined()

        static let characters = scalars.map { Character(UnicodeScalar($0)!) }
    }

    let result = (0..<length).map { _ in Statics.characters.randomElement()! }
    return String(result)
}
fal
sumber
5

untuk Swift 3.0

func randomString(_ length: Int) -> String {

    let letters : NSString = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
    let len = UInt32(letters.length)

    var randomString = ""

    for _ in 0 ..< length {
        let rand = arc4random_uniform(len)
        var nextChar = letters.character(at: Int(rand))
        randomString += NSString(characters: &nextChar, length: 1) as String
    }

    return randomString
}
WARRIOR SAHAM
sumber
1
Apakah Anda mencoba kode itu? Apakah Anda memperhatikan bahwa panjang string yang dikembalikan salah, dan hanya ada digit? Lihat stackoverflow.com/q/39566062/1187415 , yang memiliki masalah yang sama.
Martin R
@ MartinR terima kasih telah menunjukkannya. Saya telah memperbarui jawaban saya
S1LENT WARRIOR
5

Acak murni Swift Stringdari mana saja CharacterSet.

Pemakaian: CharacterSet.alphanumerics.randomString(length: 100)

extension CharacterSet {
    /// extracting characters
    /// https://stackoverflow.com/a/52133647/1033581
    public func characters() -> [Character] {
        return codePoints().compactMap { UnicodeScalar($0) }.map { Character($0) }
    }
    public func codePoints() -> [Int] {
        var result: [Int] = []
        var plane = 0
        for (i, w) in bitmapRepresentation.enumerated() {
            let k = i % 8193
            if k == 8192 {
                plane = Int(w) << 13
                continue
            }
            let base = (plane + k) << 3
            for j in 0 ..< 8 where w & 1 << j != 0 {
                result.append(base + j)
            }
        }
        return result
    }

    /// building random string of desired length
    /// https://stackoverflow.com/a/42895178/1033581
    public func randomString(length: Int) -> String {
        let charArray = characters()
        let charArrayCount = UInt32(charArray.count)
        var randomString = ""
        for _ in 0 ..< length {
            randomString += String(charArray[Int(arc4random_uniform(charArrayCount))])
        }
        return randomString
    }
}

The characters()fungsi implementasi saya tercepat dikenal .

Cur
sumber
3
func randomString(length: Int) -> String {
    // whatever letters you want to possibly appear in the output (unicode handled properly by Swift)
    let letters = "abcABC012你好吗😀🐱💥∆𝚹∌⌘"
    let n = UInt32(letters.characters.count)
    var out = ""
    for _ in 0..<length {
        let index = letters.startIndex.advancedBy(Int(arc4random_uniform(n)))
        out.append(letters[index])
    }
    return out
}
Daniel Howard
sumber
3

Saya bahkan lebih Swift-IER pelaksanaan pertanyaan:

func randomAlphanumericString(length: Int) -> String {

    let letters = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789".characters
    let lettersLength = UInt32(letters.count)

    let randomCharacters = (0..<length).map { i -> String in
        let offset = Int(arc4random_uniform(lettersLength))
        let c = letters[letters.startIndex.advancedBy(offset)]
        return String(c)
    }

    return randomCharacters.joinWithSeparator("")
}
Lachezar
sumber
3

Loop gratis, meskipun terbatas hingga 43 karakter. Jika Anda membutuhkan lebih banyak, itu dapat dimodifikasi. Pendekatan ini memiliki dua keunggulan dibandingkan hanya menggunakan UUID:

  1. Entropi yang lebih besar dengan menggunakan huruf kecil, karena UUID()hanya menghasilkan huruf besar
  2. A UUIDpaling panjang 36 karakter (termasuk 4 tanda hubung), tetapi hanya 32 karakter yang panjangnya. Jika Anda membutuhkan sesuatu yang lebih lama, atau tidak ingin menyertakan tanda hubung, gunakan base64EncodedStringpegangan ini

Juga, fungsi ini memanfaatkan a UIntuntuk menghindari angka negatif.

 func generateRandom(size: UInt) -> String {
        let prefixSize = Int(min(size, 43))
        let uuidString = UUID().uuidString.replacingOccurrences(of: "-", with: "")
        return String(Data(uuidString.utf8)
            .base64EncodedString()
            .replacingOccurrences(of: "=", with: "")
            .prefix(prefixSize))
    }

Menyebutnya secara berulang untuk memeriksa output:

for _ in 0...10 {
    print(generateRandom(size: 32))
}

Yang menghasilkan:

Nzk3NjgzMTdBQ0FBNDFCNzk2MDRENzZF
MUI5RURDQzE1RTdCNDA3RDg2MTI4QkQx
M0I3MjJBRjVFRTYyNDFCNkI5OUM1RUVC
RDA1RDZGQ0IzQjI1NDdGREI3NDgxM0Mx
NjcyNUQyOThCNzhCNEVFQTk1RTQ3NTIy
MDkwRTQ0RjFENUFGNEFDOTgyQTUxODI0
RDU2OTNBOUJGMDE4NDhEODlCNEQ1NjZG
RjM2MTUxRjM4RkY3NDU2OUFDOTI0Nzkz
QzUwOTE1N0U1RDVENDE4OEE5NTM2Rjcy
Nzk4QkMxNUJEMjYwNDJDQjhBQkY5QkY5
ODhFNjU0MDVEMUI2NEI5QUIyNjNCNkVF
CodeBender
sumber
3

Swift 5.0

// Generating Random String
func randomString(length: Int) -> String {
    let letters = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
    return String((0..<length).map{ _ in letters.randomElement()! })
}
// Calling to string
label.text = randomString(length: 3)
Sreekanth G
sumber
2

Masalah dengan respons terhadap "Saya perlu string acak" (dalam bahasa apa pun) praktis setiap solusi menggunakan spesifikasi primer cacat panjang string . Pertanyaan-pertanyaan itu sendiri jarang mengungkapkan mengapa string acak diperlukan, tetapi saya akan menantang Anda jarang membutuhkan string acak panjang, katakan 8. Apa yang Anda selalu butuhkan adalah sejumlah string unik , misalnya, untuk digunakan sebagai pengidentifikasi untuk beberapa tujuan.

Ada dua cara utama untuk mendapatkan string unik yang unik : deterministik (yang tidak acak) dan menyimpan / membandingkan (yang memberatkan). Apa yang kita lakukan? Kami menyerah hantu. Kami pergi dengan keunikan probabilistik sebagai gantinya. Artinya, kami menerima bahwa ada beberapa (betapapun kecil) risiko bahwa string kami tidak akan menjadi unik. Di sinilah pemahaman probabilitas tabrakan dan entropi sangat membantu.

Jadi saya akan ulangi kebutuhan yang tidak berubah sebagai membutuhkan sejumlah string dengan risiko pengulangan yang kecil. Sebagai contoh nyata, katakanlah Anda ingin menghasilkan potensi 5 juta ID. Anda tidak ingin menyimpan dan membandingkan setiap string baru, dan Anda ingin mereka menjadi acak, sehingga Anda menerima risiko berulang. Sebagai contoh, katakanlah risiko kurang dari 1 dalam satu triliun peluang berulang. Jadi berapa panjang tali yang Anda butuhkan? Nah, pertanyaan itu tidak ditentukan karena tergantung pada karakter yang digunakan. Tapi yang lebih penting, ini salah arah. Yang Anda butuhkan adalah spesifikasi entropi string, bukan panjangnya. Entropi dapat secara langsung terkait dengan probabilitas pengulangan dalam sejumlah string. Panjang string tidak bisa.

Dan di sinilah perpustakaan seperti EntropyString dapat membantu. Untuk menghasilkan ID acak yang memiliki peluang kurang dari 1 dalam satu triliun untuk diulang dalam 5 juta string menggunakan EntropyString:

import EntropyString

let random = Random()
let bits = Entropy.bits(for: 5.0e6, risk: 1.0e12)
random.string(bits: bits)

"Rrrj6pN4d6GBrFLH4"

EntropyStringmenggunakan set karakter dengan 32 karakter secara default. Ada set karakter yang telah ditentukan sebelumnya, dan Anda dapat menentukan karakter Anda sendiri juga. Misalnya, membuat ID dengan entropi yang sama seperti di atas tetapi menggunakan karakter hex:

import EntropyString

let random = Random(.charSet16)
let bits = Entropy.bits(for: 5.0e6, risk: 1.0e12)
random.string(bits: bits)

"135fe71aec7a80c02dce5"

Perhatikan perbedaan panjang string karena perbedaan jumlah karakter dalam set karakter yang digunakan. Risiko pengulangan dalam jumlah string potensial yang ditentukan adalah sama. Panjang string tidak. Dan yang terbaik dari semuanya, risiko pengulangan dan potensi jumlah string adalah eksplisit. Tidak perlu lagi menebak dengan panjang tali.

langit dingo
sumber
2

Jika string acak Anda harus acak-aman, gunakan ini:

import Foundation
import Security

// ...

private static func createAlphaNumericRandomString(length: Int) -> String? {
    // create random numbers from 0 to 63
    // use random numbers as index for accessing characters from the symbols string
    // this limit is chosen because it is close to the number of possible symbols A-Z, a-z, 0-9
    // so the error rate for invalid indices is low
    let randomNumberModulo: UInt8 = 64

    // indices greater than the length of the symbols string are invalid
    // invalid indices are skipped
    let symbols = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"

    var alphaNumericRandomString = ""

    let maximumIndex = symbols.count - 1

    while alphaNumericRandomString.count != length {
        let bytesCount = 1
        var randomByte: UInt8 = 0

        guard errSecSuccess == SecRandomCopyBytes(kSecRandomDefault, bytesCount, &randomByte) else {
            return nil
        }

        let randomIndex = randomByte % randomNumberModulo

        // check if index exceeds symbols string length, then skip
        guard randomIndex <= maximumIndex else { continue }

        let symbolIndex = symbols.index(symbols.startIndex, offsetBy: Int(randomIndex))
        alphaNumericRandomString.append(symbols[symbolIndex])
    }

    return alphaNumericRandomString
}
schirrmacher
sumber
1

Jika Anda hanya memerlukan pengidentifikasi unik, UUID().uuidStringdapat melayani tujuan Anda.

man1
sumber
1

Diperbarui untuk Swift 4. Gunakan variabel simpanan yang disimpan pada ekstensi kelas. Ini hanya dihitung sekali.

extension String {

    static var chars: [Character] = {
        return "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789".map({$0})
    }()

    static func random(length: Int) -> String {
        var partial: [Character] = []

        for _ in 0..<length {
            let rand = Int(arc4random_uniform(UInt32(chars.count)))
            partial.append(chars[rand])
        }

        return String(partial)
    }
}

String.random(length: 10) //STQp9JQxoq
Kawin P.
sumber
1

SWIFT 4

Menggunakan RandomNumberGenerator untuk kinerja yang lebih baik sebagai rekomendasi Apple

Penggunaan: String.random(20) Hasil:CifkNZ9wy9jBOT0KJtV4

extension String{
   static func random(length:Int)->String{
        let letters = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
        var randomString = ""

        while randomString.utf8.count < length{
            let randomLetter = letters.randomElement()
            randomString += randomLetter?.description ?? ""
        }
        return randomString
    }
}
Jad
sumber
0

Ini adalah solusi Swift -est yang bisa saya buat. Swift 3.0

extension String {
    static func random(length: Int) -> String {
        let letters = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
        let randomLength = UInt32(letters.characters.count)

        let randomString: String = (0 ..< length).reduce(String()) { accum, _ in
            let randomOffset = arc4random_uniform(randomLength)
            let randomIndex = letters.index(letters.startIndex, offsetBy: Int(randomOffset))
            return accum.appending(String(letters[randomIndex]))
        }

        return randomString
    } 
}
bojan4
sumber
-1
func randomUIDString(_ wlength: Int) -> String {

    let letters : NSString = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
    var randomString = ""

    for _ in 0 ..< wlength {
        let length = UInt32 (letters.length)
        let rand = arc4random_uniform(length)
        randomString = randomString.appendingFormat("%C", letters.character(at: Int(rand)));
    }

    return randomString
}
SteMa
sumber