Swift에서 임의의 영숫자 문자열 생성


208

Swift에서 임의의 영숫자 문자열을 어떻게 생성 할 수 있습니까?

답변:


355

스위프트 4.2 업데이트

Swift 4.2는 임의의 값과 요소를 처리 할 때 크게 개선되었습니다. 당신은 할 수 있습니다 여기 개선에 대한 자세한 내용 . 다음은 몇 줄로 축소 된 방법입니다.

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

스위프트 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
}

원래 답변 :

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
생성 된 영숫자 문자열의 길이가 6 또는 8 자인지 확인하기 위해 위의 내용을 수정할 수 있습니까?
ksa_coder

4
randomString (length : 6) 또는 randomString (length : 8)
Simon H

58

다음 은 Swiftier 구문에서 바로 사용할 수있는 솔루션 입니다 . 간단히 복사하여 붙여 넣을 수 있습니다.

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
}

좀 더 편리한 기능을 가진 프레임 워크 를 선호한다면 내 프로젝트 HandySwift를 자유롭게 확인하십시오 . 또한 임의의 영숫자 문자열에 대한 아름다운 솔루션이 포함되어 있습니다 .

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

49

다음과 같은 방법으로도 사용할 수 있습니다.

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

간단한 사용법 :

let randomString = String.random()

스위프트 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
    }
}

스위프트 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
    }
}


11

2019 년 업데이트

특이한 경우에는

성능 문제.

다음은 캐시 하는 매우 명확한 기능입니다 .

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

이것은 당신이 알려진 고정 된 경우입니다 문자 집합을.

편리한 팁 :

"abcdefghjklmnpqrstuvwxyz12345789"는 '나쁜'문자를 피합니다.

인간이 종종 혼동하는 문자는 0, o, O, i 등이 없습니다.

이는 종종 사람 고객이 사용할 예약 코드 및 유사한 코드에 대해 수행됩니다.


1
대한 Upvoting repeating:count:.
Cœur

10

간단하고 빠른 - . UUID () uuidString

// UUID에서 생성 된 문자열 (예 : "E621E1F8-C36C-495A-93FC-0C247A3E6E5F")을 반환합니다.

공용 var uuidString : 문자열 {get}

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

스위프트 3.0

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

편집하다

하지 혼동 마십시오 UIDevice.current.identifierForVendor?.uuidString임의의 값을 제공하지 않습니다 그것.


10

함께 스위프트 4.2 당신의 가장 좋은 방법은 당신이 원하는 문자가 포함 된 문자열을 생성하고 사용하는 것입니다 randomElement를 각 문자를 선택하기 :

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

이러한 변경 사항에 대한 자세한 내용은 여기를 참조하십시오 .


3
map 대신 compactMap을 사용할 수 있으며 필요하지 않습니다! 운영자. ;)
Kristaps Grinbergs

1
안녕하세요 @KristapsGrinbergs! 내 생각은 강제 언 래핑이 compactMap을 사용하는 것보다 성능이 더 좋을 것이라고 생각했다.
leogdion

6

스위프트 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
}

기본적으로이 메서드를 호출하여 함수에 전달 된 정수의 길이로 임의의 문자열을 생성합니다. 가능한 문자를 변경하려면 charactersString 문자열을 편집하십시오. 유니 코드 문자도 지원합니다.

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


2
불행히도이 버전은 때때로EXC_BAD_INSTRUCTION
Joe

Joe,이 오류를 재현 할 수있는 데모 코드가 있습니까?
어니스트 커닝햄

내가 무엇을 할 수 있는지 보자. 나는 그것을 IB 액션 아울렛에있는 그대로 호출했습니다 let random = randomString(16). EXC는 실제 장치에만 있었고 시뮬레이터에서 보지 못했으며 장치에서 간헐적이었습니다.
Joe

1
이 32 비트 장치에서 시간의 절반 충돌 이유에 대해이 SO 질문을 참조하십시오 stackoverflow.com/questions/25274265/...
julien_c

중요 : (항상) 균일 분포를 생성 random % count하지 않습니다 . 이것이 귀하와 관련이 있으면를 사용하는 다른 답변을보십시오 arc4random_uniform().
Raphael

6

전체 문자 집합을 입력하지 않으려는 사람들을 위해 :

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

스위프트 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
}

1
그 코드를 사용해 보셨습니까? 반환 된 문자열 길이가 잘못되었으며 숫자 만 있음을 알았습니까? 같은 문제가있는 stackoverflow.com/q/39566062/1187415를 살펴보십시오 .
Martin R

@MartinR 지적 해 주셔서 감사합니다. 내 답변을 업데이트했습니다
S1LENT WARRIOR

5

순수 스위프트 임의의 String어떤에서CharacterSet .

용법: 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
    }
}

characters()기능은 내가 가장 빠르게 알려진 구현 입니다.


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

더욱 신속한-IER 질문의 구현 :

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 자로 제한됩니다. 더 필요한 경우 수정할 수 있습니다. 이 방법은 UUID를 단독 사용하는 것보다 두 가지 장점이 있습니다.

  1. 대문자 UUID()만 생성 하므로 소문자를 사용하여 더 큰 엔트로피
  2. A UUID는 최대 36 자 (4 개의 하이픈 포함)이지만 최대 32 자입니다. 더 긴 것이 필요하거나 하이픈을 포함하지 않으려면 base64EncodedString핸들을 사용하여

또한이 함수는 a UInt를 사용 하여 음수를 피합니다.

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

출력을 확인하기 위해 루프에서 호출 :

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

어느 생산 :

Nzk3NjgzMTdBQ0FBNDFCNzk2MDRENzZF
MUI5RURDQzE1RTdCNDA3RDg2MTI4QkQx
M0I3MjJBRjVFRTYyNDFCNkI5OUM1RUVC
RDA1RDZGQ0IzQjI1NDdGREI3NDgxM0Mx
NjcyNUQyOThCNzhCNEVFQTk1RTQ3NTIy
MDkwRTQ0RjFENUFGNEFDOTgyQTUxODI0
RDU2OTNBOUJGMDE4NDhEODlCNEQ1NjZG
RjM2MTUxRjM4RkY3NDU2OUFDOTI0Nzkz
QzUwOTE1N0U1RDVENDE4OEE5NTM2Rjcy
Nzk4QkMxNUJEMjYwNDJDQjhBQkY5QkY5
ODhFNjU0MDVEMUI2NEI5QUIyNjNCNkVF

3

스위프트 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

"임의의 문자열이 필요합니다" 질문에 대한 응답의 문제 (언어가 무엇이든)는 실제로 모든 솔루션에 결함이있는 기본 길이 인 기본 문자열을 사용한다는 것 입니다. 임의의 문자열이 필요한 이유를 질문 자체가 거의 공개하지 않습니다,하지만 난 당신이 변함없이 필요가 몇 개의 무엇 8. 말, 당신은 거의 길이의 임의의 문자열을 필요로하지 도전 할 고유의 문자열이 어떤 목적을위한 식별자로 사용, 예를 들어,.

엄격하게 고유 한 문자열 을 얻는 두 가지 주요 방법이 있습니다 . 우리는 무엇을해야합니까? 우리는 유령을 포기합니다. 우리는 함께 갈 확률 고유성 대신. 즉, 우리는 우리의 끈이 독특하지 않을 위험이 있음을 인정합니다. 충돌 확률엔트로피를 이해하는 것이 도움이됩니다.

따라서 반복의 위험이 적은 몇 개의 문자열이 필요하다고 변하지 않는 필요성을 다시 말하겠습니다. 구체적인 예로, 5 백만 개의 잠재적 인 ID를 생성하려고한다고 가정하겠습니다. 각각의 새 문자열을 저장하고 비교하고 싶지 않으며 임의의 문자열을 원하므로 반복 위험이 있습니다. 예를 들어, 1 조 회 반복 가능성이 1 미만인 위험을 가정 해 봅시다. 그래서 어떤 길이의 문자열이 필요합니까? 글쎄, 그 질문은 사용 된 문자에 따라 다르므로 지정되지 않았습니다. 그러나 더 중요한 것은 잘못 인도 된 것입니다. 필요한 것은 길이가 아닌 문자열의 엔트로피 사양입니다. 엔트로피는 몇 개의 문자열에서 반복 확률과 직접 관련 될 수 있습니다. 문자열 길이는 할 수 없습니다.

EntropyString 과 같은 라이브러리 가 도움이 될 수 있습니다. 다음을 사용하여 5 백만 개의 문자열에서 1 조 건의 반복 확률로 1 미만의 임의 ID를 생성하려면 EntropyString다음을 사용하십시오 .

import EntropyString

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

"Rrrj6pN4d6GBrFLH4"

EntropyString기본적으로 32 자 문자 세트를 사용합니다. 사전 정의 된 다른 문자 세트가 있으며 고유 한 문자도 지정할 수 있습니다. 예를 들어, 위와 동일하지만 16 진 문자를 사용하여 ID를 생성합니다.

import EntropyString

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

"135fe71aec7a80c02dce5"

사용 된 문자 세트의 총 문자 수 차이로 인해 문자열 길이의 차이에 유의하십시오. 지정된 수의 잠재적 인 문자열에서 반복 위험은 동일합니다. 문자열 길이는 다릅니다. 그리고 무엇보다도 반복의 위험과 잠재적 인 문자열 수는 명백합니다. 더 이상 문자열 길이를 추측하지 않아도됩니다.


2

임의의 문자열이 안전한 임의의 경우 다음을 사용하십시오.

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

고유 식별자가 필요한 경우 UUID().uuidString목적을 달성 할 수 있습니다.


1

Swift 4 용으로 업데이트되었습니다. 클래스 확장에 지연 저장 변수를 사용하십시오. 이것은 한 번만 계산됩니다.

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

스위프트 4

Apple 권장 사항으로 성능 향상을 위해 RandomNumberGenerator 사용

사용법 : String.random(20) 결과 :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

이것이 내가 생각해 낼 수 있는 Swift- est 솔루션입니다. 스위프트 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
}
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.