ฉันจะสร้างสตริงตัวอักษรผสมตัวเลขแบบสุ่มใน Swift ได้อย่างไร
ฉันจะสร้างสตริงตัวอักษรผสมตัวเลขแบบสุ่มใน Swift ได้อย่างไร
คำตอบ:
อัพเดต Swift 4.2
Swift 4.2 มีการปรับปรุงที่สำคัญในการจัดการกับค่าและองค์ประกอบแบบสุ่ม คุณสามารถอ่านรายละเอียดเพิ่มเติมเกี่ยวกับการปรับปรุงดังกล่าวที่นี่ นี่คือวิธีการลดเหลือเพียงไม่กี่บรรทัด:
func randomString(length: Int) -> String {
let letters = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
return String((0..<length).map{ _ in letters.randomElement()! })
}
อัพเดต 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
}
คำตอบเดิม:
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
}
นี่เป็นทางออกที่พร้อมต่อการใช้งานในไวยากรณ์ 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"
คุณสามารถใช้วิธีดังต่อไปนี้:
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()
ไวยากรณ์ของ 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
}
}
ไวยากรณ์ของ 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
}
}
สวิฟท์:
let randomString = NSUUID().uuidString
ในกรณีที่ผิดปกตินั้น
นี่คือฟังก์ชั่นที่ชัดเจนอย่างยิ่งที่แคช :
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)
}
สิ่งนี้ใช้สำหรับเมื่อคุณมีชุดอักขระที่รู้จักและแน่นอน
เคล็ดลับที่มีประโยชน์:
ไม่มี 0, o, O, i, etc ... ตัวละครที่มนุษย์มักสับสน
มักจะทำเพื่อรหัสการจองและรหัสที่คล้ายกันซึ่งลูกค้าคนจะใช้
repeating:count:
สำหรับ
ง่ายและรวดเร็ว - UUID (). uuidString
// ส่งคืนสตริงที่สร้างจาก UUID เช่น "E621E1F8-C36C-495A-93FC-0C247A3E6E5F"
var สาธารณะ uuidString: String {รับ}
Swift 3.0
let randomString = UUID().uuidString //0548CD07-7E2B-412B-AD69-5B2364644433
print(randomString.replacingOccurrences(of: "-", with: ""))
//0548CD077E2B412BAD695B2364644433
แก้ไข
โปรดอย่าสับสนกับ UIDevice.current.identifierForVendor?.uuidString
มันจะไม่ให้ค่าสุ่ม
ด้วยSwift 4.2ทางออกที่ดีที่สุดของคุณคือการสร้างสตริงด้วยอักขระที่คุณต้องการจากนั้นใช้randomElementเพื่อเลือกอักขระแต่ละตัว:
let length = 32
let characters = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
let randomCharacters = (0..<length).map{_ in characters.randomElement()!}
let randomString = String(randomCharacters)
เวอร์ชั่น 2.2 ของ Swift
// 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
}
โดยทั่วไปเรียกวิธีการนี้ว่าจะสร้างสตริงสุ่มความยาวของจำนวนเต็มส่งไปยังฟังก์ชั่น หากต้องการเปลี่ยนอักขระที่เป็นไปได้ให้แก้ไขสตริงอักขระ String รองรับอักขระ unicode ด้วย
https://gist.github.com/gingofthesouth/54bea667b28a815b2fe33a4da986e327
EXC_BAD_INSTRUCTION
let random = randomString(16)
ฉันเป็นเพียงการเรียกมันว่าตามที่เป็นอยู่ในการดำเนินการกับเต้าเสียบ IB EXC นั้นใช้งานได้บนอุปกรณ์จริงเท่านั้นและฉันไม่เห็นมันในแบบจำลองและมันไม่ต่อเนื่องบนอุปกรณ์
random % count
ไม่ได้ (เสมอ) สร้างกระจายสม่ำเสมอ ถ้านี่เป็นที่เกี่ยวข้องกับคุณมองไปที่คำตอบอื่น ๆ arc4random_uniform()
ที่ใช้
สำหรับผู้ที่ไม่ต้องการพิมพ์ชุดอักขระทั้งหมด:
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)
}
สำหรับ 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
}
แสนบริสุทธิ์ Swift สุ่มจากส่วนใด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()
ฟังก์ชั่นการใช้งานที่เป็นที่รู้จักเร็วที่สุดของฉัน
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
}
การใช้งานSwift-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("")
}
วนฟรีแม้ว่ามันจะถูก จำกัด ที่ 43 ตัวอักษร หากคุณต้องการมากกว่านี้ก็สามารถแก้ไขได้ วิธีนี้มีข้อดีสองข้อที่ใช้ UUID เพียงอย่างเดียว:
UUID()
สร้างได้เฉพาะอักษรตัวพิมพ์ใหญ่เท่านั้นUUID
มีความยาวสูงสุดไม่เกิน 36 อักขระ (รวมถึงเครื่องหมายขีดกลาง 4 ตัว) แต่มีความยาวไม่เกิน 32 อักขระ หากคุณต้องการสิ่งที่นานกว่านี้หรือไม่ต้องการให้มีการใส่ยัติภังค์การใช้ที่base64EncodedString
จับนี้นอกจากนี้ยังมีฟังก์ชั่นนี้ทำให้การใช้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
สวิฟท์ 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)
ปัญหาเกี่ยวกับการตอบสนองต่อ"ผมต้องสตริงสุ่ม"คำถาม (ในภาษาใด) เป็นวิธีการแก้ปัญหาในทางปฏิบัติทุกใช้สเปคหลักข้อบกพร่องของความยาวสาย คำถามตัวเองไม่ค่อยเปิดเผยว่าเหตุใดจึงจำเป็นต้องใช้สตริงแบบสุ่ม แต่ฉันขอท้าให้คุณไม่ค่อยต้องการสตริงที่มีความยาวแบบสุ่มบอกว่า 8 สิ่งที่คุณต้องการอย่างสม่ำเสมอคือสตริงที่ไม่ซ้ำกันจำนวนหนึ่งตัวอย่างเพื่อใช้เป็นตัวบ่งชี้
มีสองวิธีที่นำไปสู่การได้รับสตริงที่ไม่ซ้ำกันอย่างเด็ดขาด : deterministically (ซึ่งไม่ใช่แบบสุ่ม) และการจัดเก็บ / เปรียบเทียบ (ซึ่งเป็นภาระ) พวกเราทำอะไร? พวกเรายอมแพ้ผี เราไปด้วยความน่าจะเป็นเอกลักษณ์แทน นั่นคือเรายอมรับว่ามีความเสี่ยง (เล็ก ๆ น้อย ๆ ) ที่สายของเราจะไม่ซ้ำกัน นี่คือที่การทำความเข้าใจความน่าจะเป็นของการชนและเอนโทรปีมีประโยชน์
ดังนั้นฉันจะใช้ความต้องการที่ไม่เปลี่ยนแปลงตลอดเวลาเพื่อต้องการสตริงจำนวนหนึ่งที่มีความเสี่ยงเล็กน้อยในการทำซ้ำ ตัวอย่างเช่นสมมติว่าคุณต้องการสร้างศักยภาพ 5 ล้าน ID คุณไม่ต้องการจัดเก็บและเปรียบเทียบแต่ละสตริงใหม่และคุณต้องการให้เป็นแบบสุ่มดังนั้นคุณจึงยอมรับความเสี่ยงในการทำซ้ำ ตัวอย่างเช่นสมมติว่ามีความเสี่ยงน้อยกว่า 1 ในโอกาสซ้ำซ้อน ดังนั้นคุณต้องการความยาวของสตริงอะไร? คำถามนั้นไม่ได้เน้นด้านล่างเพราะขึ้นอยู่กับตัวละครที่ใช้ แต่ที่สำคัญกว่านั้นคือเข้าใจผิด สิ่งที่คุณต้องการคือสเปคของเอนโทรปีของสายไม่ใช่ความยาว เอนโทรปีสามารถเกี่ยวข้องโดยตรงกับความน่าจะเป็นของการทำซ้ำในบางสาย ความยาวสตริงไม่สามารถทำได้
และนี่คือที่ห้องสมุดเช่นEntropyStringสามารถช่วยได้ ในการสร้างรหัสสุ่มที่มีน้อยกว่า 1 ในโอกาสล้านล้านครั้งในการทำซ้ำ 5 ล้านสายโดยใช้EntropyString
:
import EntropyString
let random = Random()
let bits = Entropy.bits(for: 5.0e6, risk: 1.0e12)
random.string(bits: bits)
"Rrrj6pN4d6GBrFLH4"
EntropyString
ใช้ชุดอักขระที่มี 32 อักขระโดยค่าเริ่มต้น มีชุดอักขระที่กำหนดไว้ล่วงหน้าอื่น ๆ และคุณสามารถระบุอักขระของคุณเองได้เช่นกัน ตัวอย่างเช่นการสร้าง ID ด้วยเอนโทรปีเดียวกันกับด้านบน แต่ใช้อักขระฐานสิบหก:
import EntropyString
let random = Random(.charSet16)
let bits = Entropy.bits(for: 5.0e6, risk: 1.0e12)
random.string(bits: bits)
"135fe71aec7a80c02dce5"
บันทึกความแตกต่างของความยาวสตริงเนื่องจากความแตกต่างของจำนวนอักขระทั้งหมดในชุดอักขระที่ใช้ ความเสี่ยงในการทำซ้ำตามจำนวนสายอักขระที่ระบุอาจเหมือนกัน ความยาวสตริงไม่ใช่ และที่สำคัญที่สุดคือความเสี่ยงในการทำซ้ำและจำนวนสายอักขระที่ชัดเจน ไม่ต้องเดาอีกต่อไปกับความยาวสตริง
หากสตริงแบบสุ่มของคุณควรปลอดภัยแบบสุ่มใช้สิ่งนี้:
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
}
หากคุณต้องการตัวระบุเฉพาะUUID().uuidString
อาจตอบสนองวัตถุประสงค์ของคุณ
อัปเดตสำหรับ 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
SWIFT 4
ใช้RandomNumberGeneratorเพื่อประสิทธิภาพที่ดีขึ้นตามคำแนะนำของ Apple
การใช้: 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
}
}
นี่คือทางออกที่รวดเร็วที่สุดที่ฉันสามารถหาได้ 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
}
}
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
}