Swift'te rastgele alfasayısal dize oluşturma


208

Swift'te nasıl rastgele bir alfasayısal dize oluşturabilirim?

Yanıtlar:


355

Swift 4.2 Güncellemesi

Swift 4.2 rastgele değerler ve unsurlarla başa çıkmada önemli gelişmeler sağlamıştır. Bu geliştirmeler hakkında daha fazla bilgiyi buradan edinebilirsiniz . Yöntem birkaç satıra indirgenmiştir:

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

Swift 3.0 Güncellemesi

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
}

Orijinal cevap:

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
}

1
Oluşturulan alfasayısal dizenin yalnızca 6 veya 8 karakter uzunluğunda olmasını sağlamak için yukarıdakileri değiştirebilmemin bir yolu var mı?
ksa_coder

4
randomString (uzunluk: 6) veya randomString (uzunluk: 8)
Simon H

58

İşte Swiftier sözdiziminde kullanıma hazır bir çözüm . Basitçe kopyalayıp yapıştırabilirsiniz:

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
}

Bazı kullanışlı özellikleri de olan bir Çerçeveyi tercih ederseniz , projemi HandySwift'e bakmaktan çekinmeyin . Ayrıca rastgele alfasayısal dizeler için güzel bir çözüm içerir :

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

49

Aşağıdaki şekilde de kullanabilirsiniz:

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

Basit kullanım:

let randomString = String.random()

Swift 3 Sözdizimi:

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

Swift 4 Sözdizimi:

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


11

Swift 4.2 ile en iyi seçeneğiniz, istediğiniz karakterlerle bir dize oluşturmak ve ardından her bir karakteri seçmek için randomElement kullanmaktır :

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

Burada bu değişiklikler hakkında daha ayrıntılı bilgi vereceğim .


3
Harita yerine compactMap'i kullanabilirsiniz ve daha sonra buna gerek yoktur! Şebeke. ;)
Kristaps Grinbergs

1
Hey @KristapsGrinbergs! Benim düşüncem, zorla açmanın compactMap kullanmaktan daha iyi bir performansa sahip olacağıydı.
leogdion

11

GÜNCELLEME 2019.

Olağandışı durumda

performans önemlidir.

İşte önbelleğe alan son derece net bir işlev :

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

Bu, sabit, bilinen bir karakter setiniz olduğunda içindir.

Kullanışlı ipucu:

"Abcdefghjklmnpqrstuvwxyz12345789" ifadesinin "kötü" karakterlerden kaçındığını unutmayın

0, o, O, i, vb. Yoktur ... insanların sıklıkla karıştırdığı karakterler.

Bu genellikle rezervasyon kodları ve insan müşterilerin kullanacağı benzer kodlar için yapılır.


1
İçin oy veriyor repeating:count:.
Junur

10

Basit ve Hızlı - UUID ().

// UUID'den oluşturulan, "E621E1F8-C36C-495A-93FC-0C247A3E6E5F" gibi bir dize döndürür

public var uuidString: 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

DÜZENLE

Değil şaşırtmak Lütfen ile UIDevice.current.identifierForVendor?.uuidStringrastgele değerler vermeyecektir buna.


6

Swift 2.2 Sürümü

// 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
}

Temelde, işleve verilen tamsayı uzunluğunda rastgele bir dize oluşturacak bu yöntemi çağırın. Olası karakterleri değiştirmek için sadece charactersString dizesini düzenleyin. Unicode karakterleri de destekler.

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


2
Bazı talihsiz nedenlerden dolayı bu sürüm bazen birEXC_BAD_INSTRUCTION
Joe

Hey Joe, bu hatayı tekrarlayabilecek bir demo kodun var mı?
Ernest Cunningham

Ne yapabileceğimi göreyim; Ben sadece bir IB eylem çıkışında olduğu gibi diyordum let random = randomString(16). EXC sadece gerçek bir cihazdaydı ve onu bir simülatörde görmedim ve cihazda aralıklıydı.
Joe

1
Bunun 32 bit aygıtlarda neden yarı yarıya çöktüğünün nedeni için bu SO sorusuna bakın: stackoverflow.com/questions/25274265/…
julien_c

Önemli: random % count yok değil (her zaman) düzgün bir şekilde dağılmasını oluşturun. Bu sizinle ilgiliyse, kullanılan diğer yanıtlara bakın arc4random_uniform().
Raphael

6

Tüm karakter setini yazmak istemeyen kişiler için:

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

5

Swift 3.0 için

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
}

1
Bu kodu denedin mi? Döndürülen dize uzunluğunun yanlış olduğunu ve yalnızca rakam olduğunu fark ettiniz mi? Aynı soruna sahip olan stackoverflow.com/q/39566062/1187415 adresine bakın .
Martin R

@MartinR bunu işaret ettiğiniz için teşekkürler. cevabımı güncelledim
S1LENT WARRIOR

5

StringHerhangi birinden rastgele bir SwiftCharacterSet .

Kullanımı: 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
    }
}

Bu characters()fonksiyon bilinen en hızlı uygulamam .


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
}

3

Benim daha Swift-ier soruya uygulanması:

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

3

43 karakterle sınırlı olmasına rağmen döngü içermez. Daha fazlasına ihtiyacınız varsa değiştirilebilir. Bu yaklaşımın yalnızca bir UUID kullanımına kıyasla iki avantajı vardır:

  1. UUID()Yalnızca büyük harfler ürettiği için küçük harfler kullanarak daha büyük Entropi
  2. A UUIDen fazla 36 karakter uzunluğundadır (4 kısa çizgi dahil), ancak yalnızca 32 karakter uzunluğundadır. Daha uzun bir şeye ihtiyacınız varsa veya kısa çizgiler dahil edilmesini istemiyorsanız, bu base64EncodedStringtutamaçların kullanımı

Ayrıca, bu işlev UIntnegatif sayıları önlemek için a kullanır.

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

Çıktıyı kontrol etmek için bir döngüde çağırmak:

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

Hangi üretir:

Nzk3NjgzMTdBQ0FBNDFCNzk2MDRENzZF
MUI5RURDQzE1RTdCNDA3RDg2MTI4QkQx
M0I3MjJBRjVFRTYyNDFCNkI5OUM1RUVC
RDA1RDZGQ0IzQjI1NDdGREI3NDgxM0Mx
NjcyNUQyOThCNzhCNEVFQTk1RTQ3NTIy
MDkwRTQ0RjFENUFGNEFDOTgyQTUxODI0
RDU2OTNBOUJGMDE4NDhEODlCNEQ1NjZG
RjM2MTUxRjM4RkY3NDU2OUFDOTI0Nzkz
QzUwOTE1N0U1RDVENDE4OEE5NTM2Rjcy
Nzk4QkMxNUJEMjYwNDJDQjhBQkY5QkY5
ODhFNjU0MDVEMUI2NEI5QUIyNjNCNkVF

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)

2

"Rastgele dizelere ihtiyacım var" sorularına (hangi dilde olursa olsun) yanıtlar ile ilgili sorun , hemen hemen her çözüm dize uzunluğunun hatalı bir birincil belirtimini kullanır . Rasgele dizeleri ihtiyaç vardır neden soruları kendileri nadiren ortaya, ama kaçınılmaz bir ihtiyaç bazı sayıdır Ne 8. demek, nadiren uzunlukta rasgele dizeleri ihtiyaç sorun olur benzersiz dizeleri bazı amaçla tanımlayıcılar olarak kullanmak, örneğin,.

Kesinlikle benzersiz dizeler elde etmenin iki önde gelen yolu vardır : deterministik olarak (rastgele değil) ve depola / karşılaştır (zahmetli). Biz ne yaptık? Hayaleti bırakıyoruz. Onun yerine olasılıksal teklikle gidiyoruz . Yani, dizelerimizin benzersiz olmayacağı konusunda küçük (ancak küçük) bir risk olduğunu kabul ediyoruz. Bu nerede anlayış çarpışma olasılığı ve entropiyi yararlıdır.

Bu yüzden, değişmez ihtiyacı küçük bir tekrarlama riski olan bir dizi dizeye ihtiyaç duyduğunu yeniden ifade edeceğim. Somut bir örnek olarak, 5 milyon kimlik potansiyeli oluşturmak istediğinizi varsayalım. Her yeni dizeyi saklamak ve karşılaştırmak istemezsiniz ve rastgele olmasını istersiniz, bu nedenle tekrarlama riskini kabul edersiniz. Örneğin, bir trilyon tekrarlama şansında 1'den az bir risk olduğunu varsayalım. Peki, ne kadar uzunluğa ihtiyacınız var? Bu soru, kullanılan karakterlere bağlı olduğu için yeterince belirsiz. Ama daha da önemlisi, yanlış yönlendirilmiş. İhtiyacınız olan şey, dizelerin entropisinin uzunluğu değil bir spesifikasyonu. Entropi, bazı dizelerde tekrarlanma olasılığı ile doğrudan ilişkili olabilir. Dize uzunluğu olamaz.

EntropyString gibi bir kütüphane bu noktada yardımcı olabilir. 5 milyon dizede 1 trilyondan daha az tekrarlama şansına sahip rastgele kimlikleri kullanarak EntropyString:

import EntropyString

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

"Rrrj6pN4d6GBrFLH4"

EntropyStringvarsayılan olarak 32 karakterden oluşan bir karakter seti kullanır. Önceden tanımlanmış başka karakter setleri de vardır ve kendi karakterlerinizi de belirleyebilirsiniz. Örneğin, yukarıdakiyle aynı entropiye sahip ancak onaltılık karakterler kullanan kimlikler oluşturma:

import EntropyString

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

"135fe71aec7a80c02dce5"

Kullanılan karakter kümesindeki toplam karakter sayısındaki farktan dolayı dize uzunluğu farkına dikkat edin. Belirtilen sayıda potansiyel dizede tekrarlama riski aynıdır. Dize uzunlukları değildir. Ve en önemlisi, tekrarlama riski ve potansiyel dizeler açıktır. Dize uzunluğu ile artık tahmin yok.


2

Rastgele dizeniz güvenli-rastgele olmalı, bunu kullanın:

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
}

1

Sadece benzersiz bir tanımlayıcıya ihtiyacınız varsa UUID().uuidString, amaçlarınıza hizmet edebilir.


1

Swift 4 için güncellendi. Sınıf uzantısında tembel bir depolanmış değişken kullanın. Bu sadece bir kez hesaplanır.

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

1

SWIFT 4

RandomNumberGenerator kullanmaApple önerisi olarak daha iyi performans için

Kullanım: String.random(20) Sonuç: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
    }
}

0

Bu Swift ben ile gelebilir en çözümdür. 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
    } 
}

-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
}
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.