Was ist der einfachste Weg, um in Swift von einer einzelnen Zeichenfolge in einen ASCII-Wert zu konvertieren?

70

Ich möchte nur den ASCII-Wert einer einzelnen Zeichenfolge in Swift abrufen. So mache ich es gerade:

var singleChar = "a"
println(singleChar.unicodeScalars[singleChar.unicodeScalars.startIndex].value) //prints: 97

Das ist aber so hässlich. Es muss einen einfacheren Weg geben.

DavidNorman
quelle

Antworten:

119

Bearbeiten / Aktualisieren von Swift 5.2 oder höher

extension StringProtocol {
    var asciiValues: [UInt8] { compactMap(\.asciiValue) }
}

"abc".asciiValues  // [97, 98, 99]

In Swift 5 können Sie die neuen Zeicheneigenschaften isASCII und asciiValue verwenden

Character("a").isASCII       // true
Character("a").asciiValue    // 97

Character("á").isASCII       // false
Character("á").asciiValue    // nil

Alte Antwort

Sie können eine Erweiterung erstellen:

Swift 4.2 oder höher

extension Character {
    var isAscii: Bool {
        return unicodeScalars.allSatisfy { $0.isASCII }
    }
    var ascii: UInt32? {
        return isAscii ? unicodeScalars.first?.value : nil
    }
}

extension StringProtocol {
    var asciiValues: [UInt32] {
        return compactMap { $0.ascii }
    }
}

Character("a").isAscii  // true
Character("a").ascii    // 97

Character("á").isAscii  // false
Character("á").ascii    // nil

"abc".asciiValues            // [97, 98, 99]
"abc".asciiValues[0]         // 97
"abc".asciiValues[1]         // 98
"abc".asciiValues[2]         // 99
Leo Dabus
quelle
14
UnicodeScalar("1")!.value // returns 49

Swift 3.1

Joe
quelle
@ixany Forced Unwraps gibt es aus einem bestimmten Grund. In diesem Fall sind wir zu 101% sicher, dass der Initialisierer nicht fehlschlägt ("1" ist ein gültiges Zeichen).
Cristik
@ Cristik nicht einverstanden. Im Allgemeinen können Sie nicht sicher sein, dass ein Eingabewert nicht für immer fehlschlägt. Warum also nicht auf Nummer sicher gehen? Besserer Ansatz wäre : guard let value = UnicodeScalar("1")?.value else { return }.
Ixany
@ixany, stimmst du nicht zu, dass "1" ein gültiges Zeichen ist? :)
Cristik
@Cristik if letoder guard letAussagen existieren auch aus einem Grund. Ich bin überzeugt, dass Sie, wann immer möglich, auf Nummer sicher gehen sollten. Und dass wir als erfahrener Entwickler allen Neulingen hier bei stackoverflow einen guten Codierungsstil und Best Practices bieten sollten. Es war nicht als Straftat gedacht.
Ixany
@ixany, ja, stimmte zu, und ich vermeide erzwungenes Auspacken so weit wie möglich. Es gibt jedoch (seltene oder sehr seltene) Fälle, in denen erzwungenes Auspacken sinnvoll ist. Ihre "nie eine gute Idee" schien mir im Antwortkontext ein wenig drastisch, deshalb habe ich geantwortet :)
Cristik
11

Jetzt in Xcode 7.1 und Swift 2.1

var singleChar = "a"

singleChar.unicodeScalars.first?.value
wakeupsumo
quelle
10

Sie können den CharakterAtIndex von NSString verwenden , um dies zu erreichen ...

var singleCharString = "a" as NSString
var singleCharValue = singleCharString.characterAtIndex(0)
println("The value of \(singleCharString) is \(singleCharValue)")  // The value of a is 97
Timgcarlson
quelle
1
@ Vacawama Swift 4, ich erhalte Fehler error: value of type 'String' has no member 'character'. aber wenn "a" als NSString verwendet wird, funktioniert es :)
Kamaldeep singh Bhatia
4

Swift 4.2

Der einfachste Weg, um ASCII-Werte aus einer Swift-Zeichenfolge abzurufen, ist unten aufgeführt

let str = "Swift string"
for ascii in str.utf8 {
    print(ascii)
}

Ausgabe:

83
119
105
102
116
32
115
116
114
105
110
103
aios
quelle
Dies sind nicht die ASCII-Werte. Dies gibt ein Array von Bytes zurück. Ein anderes Zeichen als ASCII gibt mehrere Bytes ohne Beziehung zur ASCII-Tabelle zurück.
Leo Dabus
versuchen Sie let str = "😀" for ascii in str.utf8 { print(ascii) }// 240, 159, 152, 128`
Leo Dabus
3

Die Art und Weise, wie Sie es tun, ist richtig. Wenn Ihnen die Ausführlichkeit der Indizierung nicht gefällt, können Sie sie vermeiden, indem Sie durch die Unicode-Skalare blättern:

var x : UInt32 = 0
let char = "a"
for sc in char.unicodeScalars {x = sc.value; break}

breakIn diesem Fall können Sie das natürlich weglassen , da es nur einen Unicode-Skalar gibt.

Oder konvertieren Sie in ein Array und verwenden Sie die Int-Indizierung (das letzte Mittel der Verzweifelten):

let char = "a"
let x = Array(char.unicodeScalars)[0].value
matt
quelle
3

Ein etwas kürzerer Weg, dies zu tun, könnte sein:

first(singleChar.unicodeScalars)!.value

Wie bei der tiefgestellten Version stürzt dies ab, wenn Ihre Zeichenfolge tatsächlich leer ist. Wenn Sie sich also nicht 100% sicher sind, verwenden Sie die Option:

if let ascii = first(singleChar.unicodeScalars)?.value {

}

Oder wenn Sie extra-paranoid sein wollen,

if let char = first(singleChar.unicodeScalars) where char.isASCII() {
    let ascii = char.value
}
Fluggeschwindigkeit
quelle
3

Hier ist meine Implementierung, die ein Array der ASCII-Werte zurückgibt.

extension String {

    func asciiValueOfString() -> [UInt32] {

      var retVal = [UInt32]()
      for val in self.unicodeScalars where val.isASCII() {
          retVal.append(UInt32(val))
      }
      return retVal
    }
}

Hinweis: Ja, es ist Swift 2-kompatibel.

Sakiboy
quelle
2

Swift 4.1

https://oleb.net/blog/2017/11/swift-4-strings/

let flags = "99_problems"
flags.unicodeScalars.map {
    "\(String($0.value, radix: 16, uppercase: true))"
}

Ergebnis:

["39", "39", "5F", "70", "72", "6F", "62", "6C", "65", "6D", "73"]

rustyMagnet
quelle
versuchen Sie let flags = "😀" flags.unicodeScalars.map { "\(String($0.value, radix: 16, uppercase: true))" } // "1F600"
Leo Dabus
1
var singchar = "a" as NSString

print(singchar.character(at: 0))

Swift 3.1

Shauket Sheikh
quelle
1

Es gibt auch den UInt8-Initialisierer (ascii: Unicode.Scalar) auf UInt8.

var singleChar = "a"
UInt8(ascii: singleChar.unicodeScalars[singleChar.startIndex])
Anders
quelle
Beachten Sie, dass dies ein nicht fehlbarer Initialisierer ist. Es stürzt ab, wenn Sie ein ungültiges Zeichen übergeben, dessen Wert außerhalb des ASCII-Bereichs 0 .. <128 liegt. "Schwerwiegender Fehler:
Codepunktwert
try var singleChar = "😀" UInt8(ascii: singleChar.unicodeScalars[singleChar.startIndex])// Schwerwiegender Fehler: Codepunktwert passt nicht in ASCII: Datei /AppleInternal/BuildRoot/Library/Caches/com.apple.xbs/Sources/swiftlang/swiftlang-1200.2.10.322/swift/stdlib/public/core/UnicodeScalar .swift, Linie 354`
Leo Dabus
0

Swift 4

print("c".utf8["c".utf8.startIndex])

oder

let cu = "c".utf8
print(cu[cu.startIndex])

Beide drucken 99. Funktioniert für jedes ASCII-Zeichen.

PJ_Finnegan
quelle
0

Swift 4+

Char zu ASCII

let charVal = String(ch).unicodeScalars
var asciiVal = charVal[charVal.startIndex].value

ASCII zu Char

let char = Character(UnicodeScalar(asciiVal)!)
Mohit Kumar
quelle
versuchen Sie let charVal = String("😀").unicodeScalars charVal[charVal.startIndex].value// 128512
Leo Dabus
0

Mit Swift 5 können Sie einen der folgenden Ansätze auswählen, um die numerische ASCII-Darstellung eines Zeichens zu erhalten.


# 1. Verwenden Characterder asciiValueEigenschaft von

Characterhat eine Eigenschaft namens asciiValue. asciiValuehat die folgende Erklärung:

var asciiValue: UInt8? { get }

Der ASCII-Codierungswert dieses Zeichens, wenn es sich um ein ASCII-Zeichen handelt.

Die folgenden Playground-Beispielcodes zeigen, wie asciiValueSie den ASCII-Codierungswert eines Zeichens ermitteln:

let character: Character = "a"
print(character.asciiValue) //prints: Optional(97)
let string = "a"
print(string.first?.asciiValue) //prints: Optional(97)
let character: Character = "👍"
print(character.asciiValue) //prints: nil

# 2. Verwenden von Character's isASCIIEigenschaft und Unicode.Scalar' s valueEigenschaft

Alternativ können Sie überprüfen, ob das erste Zeichen einer Zeichenfolge ein ASCII-Zeichen ist (mithilfe Characterder isASCIIEigenschaft '), und dann die numerische Darstellung des ersten Unicode-Skalars (mithilfe Unicode.Scalarder valueEigenschaft ') abrufen . Der folgende Beispielcode für den Spielplatz zeigt, wie Sie vorgehen müssen:

let character: Character = "a"
if character.isASCII, let scalar = character.unicodeScalars.first {
    print(scalar.value)
} else {
    print("Not an ASCII character")
}
/*
 prints: 97
 */
let string = "a"
if let character = string.first, character.isASCII, let scalar = character.unicodeScalars.first {
    print(scalar.value)
} else {
    print("Not an ASCII character")
}
/*
 prints: 97
 */
let character: Character = "👍"
if character.isASCII, let scalar = character.unicodeScalars.first {
    print(scalar.value)
} else {
    print("Not an ASCII character")
}
/*
 prints: Not an ASCII character
 */
Imanou Petit
quelle