我有一个包含单词和空格的字符串,“2h 3m 1s”。我想从中提取2h
;所以在第一空间之前得到一切。
var date = "1,340d 1h 15m 52s" // I want to extract "1,340d".
这样做的最佳做法是什么?什么子串函数是最好的方法?
答案 0 :(得分:21)
如果您的字符串很重,componentsSeparatedByString()
往往会更快。
Swift 2:
var date = "1,340d 1h 15m 52s"
if let first = date.componentsSeparatedByString(" ").first {
// Do something with the first component.
}
Swift 3/4:
if let first = date.components(separatedBy: " ").first {
// Do something with the first component.
}
答案 1 :(得分:9)
在此上下文中,.componentsSeparatedByString(" ")
方法和characters.split(" ")
方法都不是“最佳方法”。这两种方法都将遍历完整的String
对象,并作为结果提供String
数组。只有在计算了数组之后,我们才提取该数组的第一个条目。如果我们处理一个巨大的字符串,在这种情况下这是非常不必要的,并且会导致不必要的开销。
相反,对于一个巨大的字符串,需要采用以下方法:
let firstDateEntryFast = date.substringToIndex((date.rangeOfString(" ")?.first)!)
这将查找第一次出现" "
的索引,然后将子串从原始字符串的开头仅返回到第一次出现。也就是说,它永远不会调查或使用原始(在此上下文中:假设为大)字符串超出它们第一个" "
出现点。
但是,您应该注意,由于强制解包(运算符(!)),如果字符串不包含任何" "
实例,则会在运行时崩溃。因此,为了保持安全并遵循Swift的可选约定,请在if let
子句中使用它:
if let myRange = date.rangeOfString(" ") {
let firstDateEntryFast = date.substringToIndex(myRange.first!)
// at this point, you know myRange is non-empty, and hence, .first can be
// force-unwrapped
}
else {
let firstDateEntryFast = date
// no " " separation, unexpected? -> action
}
在我的第一个答案版本中,split
可以作为替代方案(与componentsSeparatedByString
相比):
var date = "1,340d 1h 15m 52s"
let dateAsArray = date.characters.split(" ").map{ String($0) }
let firstDateEntry = dateAsArray[0]
或者,跳过将它们全部存储在数组中并直接获取第一个条目
var date = "1,340d 1h 15m 52s"
let firstDateEntryDirectly = String(date.characters.split(" ")[0])
答案 2 :(得分:3)
Swift 3版
var str = "Hello, playground one two three"
let firstWord = str.components(separatedBy: " ").first
答案 3 :(得分:2)
根据您的要求使用以下代码
var date = "1,340d 1h 15m 52s"
print((date.componentsSeparatedByString(" ") as NSArray).objectAtIndex(0));
答案 4 :(得分:0)
快捷键5
var name = ""
if let optionalName = someOptionalString as? String {
name = optionalName.contains(" ") ? (name.components(separatedBy: " ").first ?? "") : optionalName
}
首先,我们确保字符串不为nil。 然后,我们使用三元运算符根据它是否包含任何空格对它进行相应的分配。