我是Swift的新手,在遍历Apple文档和其他资料后,我不清楚如何使用多个字符作为分隔符来提取子字符串。例如:我有一个看起来像这样的字符串:
A.1值1 B.2值2 E值3 C值4
,需要将值1-4分配给不同的变量。
答案 0 :(得分:0)
•可能的解决方案:
1.分隔所有元素(分隔符:空白)
2.以2进行2迭代,并使用键/值系统,例如Dictionary
。
3.然后从键中读取每个值
步骤1:
let string = "A.1 value1 B.2 value2 E value3 C value4"
let components = string.components(separatedBy: CharacterSet.whitespaces)
第2步:
var dictionary: [String: String] = [:]
stride(from: 0, to: components.count - 1, by: 2).forEach({
dictionary[components[$0]] = components[$0+1]
})
或
let dictionary = stride(from: 0, to: components.count - 1, by: 2).reduce(into: [String: String]()) { (result, currentInt) in
result[components[currentInt]] = components[currentInt+1]
}
dictionary
是["A.1": "value1", "C": "value4", "E": "value3", "B.2": "value2"]
Inspiration代替我很少使用的stride(from:to:)
。
第3步:
let name = dictionary["A.1"]
let surname = dictionary["C"]
•潜在问题:
如果您有:
let string = "A.1 value One B.2 value2 E value3 C value4"
您想要“值One”,并且由于存在空格,您会遇到一些问题,因为if会给出错误的结果(因为存在分隔符)。
您将获得dictionary
的[[A.1“:”值“,”一个“:” B.2“,” value2“:” E“,” value3“:” C“]。< / p>
因此,您可以改用正则表达式:A.1(.*)B.2(.*)E(.*)C(.*)
(例如)。
let string = "A.1 value One B.2 value2 E value3 C value4"
let regex = try! NSRegularExpression(pattern: "A.1(.*)B.2(.*)E(.*)C(.*)", options: [])
regex.enumerateMatches(in: string, options: [], range: NSRange(location: 0, length: string.utf16.count)) { (result, flags, stop) in
guard let result = result,
let aValueRange = Range(result.range(at: 1), in: string),
let bValueRange = Range(result.range(at: 2), in: string),
let cValueRange = Range(result.range(at: 4), in: string),
let eValueRange = Range(result.range(at: 3), in: string) else { return }
let aValue = string[aValueRange].trimmingCharacters(in: CharacterSet.whitespaces)
print("aValue: \(aValue)")
let bValue = string[bValueRange].trimmingCharacters(in: CharacterSet.whitespaces)
print("bValue: \(bValue)")
let cValue = string[cValueRange].trimmingCharacters(in: CharacterSet.whitespaces)
print("cValue: \(cValue)")
let eValue = string[eValueRange].trimmingCharacters(in: CharacterSet.whitespaces)
print("eValue: \(eValue)")
}
输出:
$>aValue: value One
$>bValue: value2
$>cValue: value4
$>eValue: value3
请注意,修剪可能位于正则表达式中,但是我不特别喜欢过于复杂的正则表达式。
答案 1 :(得分:0)
我喜欢这种事情的正则表达式。
我将非常实际地理解您,并假设要找到的子字符串以"A.1"
,"B.2"
,"E"
和"C"
开头,并且除最后一个子字符串(其后跟原始字符串的末尾)外,所有字符均在其前面和后跟一个空格。此外,我将非常简单地假设诸如"E"
之类的分隔符不能以任何 other 方式出现在我们的字符串中。然后,我们可以使用适当的模式捕获每个子字符串:
let s = "A.1 harpo B.2 chico E zeppo C groucho"
let p1 = "^A\\.1 (.*) B\\.2 "
let p2 = " B\\.2 (.*) E "
let p3 = " E (.*) C "
let p4 = " C (.*)$"
let patts = [p1,p2,p3,p4]
var result = [String]()
for patt in patts {
let regex = try! NSRegularExpression(pattern: patt, options: [])
if let match = regex.firstMatch(in: s, options: [],
range: NSRange(s.startIndex..<s.endIndex, in: s)) {
let r = match.range(at: 1)
result.append((s as NSString).substring(with: r))
}
}
// result is now ["harpo", "chico", "zeppo", "groucho"]
我们现在将四个所需的子字符串提取到一个数组中,然后从那里进行处理很简单。
请注意,我们不对空格做任何假设。即使目标子字符串包含空格,以上代码也可以很好地工作,因为我们仅吸引定界符。例如,如果原始字符串为
let s = "A.1 the rain B.2 in spain E stays mainly C in the plain"
然后result
是数组
["the rain", "in spain", "stays mainly", "in the plain"]
但是,我应该指出,执行这种操作的另一种方法是使用扫描程序走原始字符串。您可能更喜欢这样做,因为这里实际上不需要正则表达式,并且如果您不知道正则表达式,您会发现这种用法更加清晰。因此,这里使用扫描仪进行了重写。请注意,我们最终得到了四个Optional NSString对象,因为Scanner实际上是Objective-C Cocoa Foundation的东西,但是根据需要将它们变成String对象并不难:
let s = "A.1 the rain B.2 in spain E stays mainly C in the plain"
let scan = Scanner(string: s)
scan.scanString("A.1 ", into: nil)
var r1 : NSString? = nil
scan.scanUpTo(" B.2 ", into: &r1)
scan.scanString("B.2 ", into: nil)
var r2 : NSString? = nil
scan.scanUpTo(" E ", into: &r2)
scan.scanString("E ", into: nil)
var r3 : NSString? = nil
scan.scanUpTo(" C ", into: &r3)
scan.scanString("C ", into: nil)
var r4 : NSString? =
(scan.string as NSString).substring(from: scan.scanLocation) as NSString
r1 // the rain
r2 // in spain
r3 // stays mainly
r4 // in the plain