[英]Swift: Extract a Substring from a String
我有一個可以是以下任一類型的字符串:
tempString = "What? The ID: 54673 Over there"
tempString = "Jump... ID: 4561E how high"
基本上,我想從字符串中檢索五個字符的 ID:。 對於大多數語言,我可以通過查找 ID: 來實現這一點,向其添加 4 以到達 ID: 的開頭,然后獲取接下來的五個字符。
例如,在 Excel 中:
=MID("Jump... ID: 4561E how high",FIND("ID:","Jump... ID: 4561E how high")+4, 5)
將 = 4561E。
我們如何用 Swift 做到這一點?
您可以在字符串上使用range(of:)
來查找子字符串的range
,然后使用該range
的upperBound
索引原始字符串以獲取從該點開始的子字符串。 最后, prefix(5)
允許您獲取該子字符串的前 5 個字符, String()
將Substring.Subsequence
回正常的String
:
if let range = tempString.range(of: "ID: ") {
let ident = String(tempString[range.upperBound...].prefix(5))
print(ident)
}
注意: range(of:)
來自Foundation框架,因此需要import Foundation
或import
其他使用Foundation
框架,例如UIKit
或Cocoa
。
在“ID:”之后從 [0-9] 或 [AF] 中查找前 5 個字符的正則表達式方法(僅在不能使用 AZ 的情況下才使用十六進制字母)。
if let range = string.range(of: "(?<=ID: )[0-9A-F]{5}", options: .regularExpression) {
let id = string[range] //
// if you need a String instead of a substring
let stringID = String(string[range])
}
編輯/更新:
查看您的答案,看起來要求與您的原始帖子完全不同,無論如何要找到 8 個十六進制字符后跟連字符的 IF 復合,然后是 4 個六進制字符后跟連字符(3 次)而不是 12 個十六進制字符,您可以使用以下正則表達式"([0-9a-f]{8}-)([0-9a-f]{4}-){3}([0-9a-f]{12})"
:
let dataString = """
{
"@odata.context": "$metadata#GeoFences(Points())/$entity",
"ID": "2b2a2abc-5962-4290-92b4-773025ffd50b",
"Points": {
"POINT_TYPE": "F",
"POINT_NUM": 0,
"LATITUDE": 32.92197686725423,
"LONGITUDE": -117.04306932263532,
"parent_ID": "2b2a2abc-5962-4290-92b4-773025ffd50b"
},
"GEOFENCE_NAME": "New Fence",
"GEOFENCE_TYPE": "O",
"PRIVACY": "X",
"CENTER_LAT": 32.92043316309709,
"CENTER_LONG": -117.04286922250975,
"ZOOM_LAT": 0.006238797350533787,
"ZOOM_LONG": 0.005345531926053582,
"PATH_TOLERANCE": 5,
"ENTRANCE_TOLERANCE": 5
}
"""
if let range = dataString.range(of: "([0-9a-f]{8}-)([0-9a-f]{4}-){3}([0-9a-f]{12})", options: .regularExpression) {
let id = dataString[range] // 4561E
print("ID:", id)
// if you need a String instead of a substring
let stringID = String(dataString[range])
print("stringID:", stringID)
}
這將打印
編號:2b2a2abc-5962-4290-92b4-773025ffd50b
字符串 ID:2b2a2abc-5962-4290-92b4-773025ffd50b
請注意,您的代碼將導致"2b2a2abc-5962-4290-92b4-773025ffd50
編輯/更新2:
考慮到您的字符串是 JSON,您可以簡單地解碼您的字符串 id:
struct Root: Codable {
let id: String
enum CodingKeys: String, CodingKey {
case id = "ID"
}
}
do {
let id = try JSONDecoder().decode(Root.self, from: Data(dataString.utf8)).id
print(id) // "2b2a2abc-5962-4290-92b4-773025ffd50b"
} catch {
print(error)
}
如果您需要解碼所有數據:
struct Root: Codable {
let odataContext, id: String
let points: Points
let geofenceName, geofenceType, privacy: String
let centerLat, centerLong, zoomLat, zoomLong: Double
let pathTolerance, entranceTolerance: Int
enum CodingKeys: String, CodingKey {
case odataContext = "@odata.context", id = "ID", points = "Points", geofenceName = "GEOFENCE_NAME", geofenceType = "GEOFENCE_TYPE", privacy = "PRIVACY", centerLat = "CENTER_LAT", centerLong = "CENTER_LONG", zoomLat = "ZOOM_LAT", zoomLong = "ZOOM_LONG", pathTolerance = "PATH_TOLERANCE", entranceTolerance = "ENTRANCE_TOLERANCE"
}
}
struct Points: Codable {
let pointType: String
let pointNum: Int
let latitude, longitude: Double
let parentID: String
enum CodingKeys: String, CodingKey {
case pointType = "POINT_TYPE", pointNum = "POINT_NUM", latitude = "LATITUDE", longitude = "LONGITUDE", parentID = "parent_ID"
}
}
do {
let root = try JSONDecoder().decode(Root.self, from: Data(dataString.utf8))
print("ID:", root.id) // ID: 2b2a2abc-5962-4290-92b4-773025ffd50b
print("Root:", root) // Root: Root(odataContext: "$metadata#GeoFences(Points())/$entity", id: "2b2a2abc-5962-4290-92b4-773025ffd50b", points: __lldb_expr_111.Points(pointType: "F", pointNum: 0, latitude: 32.92197686725423, longitude: -117.04306932263532, parentID: "2b2a2abc-5962-4290-92b4-773025ffd50b"), geofenceName: "New Fence", geofenceType: "O", privacy: "X", centerLat: 32.92043316309709, centerLong: -117.04286922250975, zoomLat: 0.0062387973505337885, zoomLong: 0.005345531926053582, pathTolerance: 5, entranceTolerance: 5)
} catch {
print(error)
}
對於您的情況,可以使用 NSRegularExpression:
let tempString1 = "What? The ID: 54673 Over there"
let tempString2 = "Jump... ID: 4561E how high"
func matches(for regex: String, in text: String) -> [String] {
do {
let regex = try NSRegularExpression(pattern: regex)
let results = regex.matches(in: text,
range: NSRange(text.startIndex..., in: text))
return results.map {
String(text[Range($0.range, in: text)!])
}
} catch let error {
print("invalid regex: \(error.localizedDescription)")
return []
}
}
var res1 = matches(for: "[0-9]+[A-Z]*", in: tempString1) // 54673
var res2 = matches(for: "[0-9]+[A-Z]*", in: tempString2) // 4561E
好的,我開始這個練習是因為我懶得解碼 JSON,因為我必須構建結構並使它們正確。 所以,我想我會很快做一個子串。 好吧,解碼會更好、更快、更准確,但我將在下面展示我的代碼。 基本上,我想從 JSON 字符串中獲取 ID:
{
"@odata.context": "$metadata#GeoFences(Points())/$entity",
"ID": "2b2a2abc-5962-4290-92b4-773025ffd50b",
"Points": {
"POINT_TYPE": "F",
"POINT_NUM": 0,
"LATITUDE": 32.92197686725423,
"LONGITUDE": -117.04306932263532,
"parent_ID": "2b2a2abc-5962-4290-92b4-773025ffd50b"
},
"GEOFENCE_NAME": "New Fence",
"GEOFENCE_TYPE": "O",
"PRIVACY": "X",
"CENTER_LAT": 32.92043316309709,
"CENTER_LONG": -117.04286922250975,
"ZOOM_LAT": 0.006238797350533787,
"ZOOM_LONG": 0.005345531926053582,
"PATH_TOLERANCE": 5,
"ENTRANCE_TOLERANCE": 5
}
我的代碼如下。 我很快就會用解碼替換它。 變量 id 確實包含 id。
var foundI :Bool = false
var iIndex = 0
for (index, char) in dataString.enumerated() {
if char == "I" {
foundI = true
iIndex = index
} else if char == "D" {
if foundI == true && index == iIndex+1 {
var suffixStr = String(dataString.dropFirst(iIndex+5))
var id = String(suffixStr.prefix(36))
print("New String \(id)")
}
}
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.