Swift 4.2使用多个字符提取子字符串是定界符

时间:2018-11-26 09:02:31

标签: ios swift string

我是Swift的新手,在遍历Apple文档和其他资料后,我不清楚如何使用多个字符作为分隔符来提取子字符串。例如:我有一个看起来像这样的字符串:

A.1值1 B.2值2 E值3 C值4

,需要将值1-4分配给不同的变量。

2 个答案:

答案 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