我有一个从文本文件中获取的字符串。
文字档案:
Line 1
Line 2
Line 3
...
我想将它转换为数组,每行一个数组元素。
[ "Line 1", "Line 2", "Line 3", ... ]
根据文件的保存方式,字符串可以采用以下形式之一:
string = "Line 1\nLine 2\nLine 3\n..."
其中\n
是新行(换行符)
string = "Line 1\r\nLine 2\r\nLine 3\r\n..."
其中\r
是回车符。
据我了解,\n
目前常用于Apple / Linux,而\r\n
则用于Windows。
如何在任何换行符处拆分字符串以获取没有任何空元素的String数组?
以下有几种解决方案。在这一点上,我没有任何令人信服的理由选择一个比其他更正确。可能影响选择的一些因素可能是(1)“Swift”如何以及(2)对于非常长的字符串有多快。您可以通过提升其中一个或多个和/或发表评论来提供反馈。
答案 0 :(得分:47)
Swift 5或更高版本
您可以使用新的String
媒体资源isNewline
拆分Character
:
let sentence = "Line 1\nLine 2\nLine 3\n"
var lines = sentence.split { $0.isNewline }
print(lines) // "[Line 1, Line 2, Line 3]"
原始答案
您可以使用String方法 enumerateLines :
枚举字符串中的所有行。
Swift 3或更高版本
let sentence = "Line 1\nLine 2\nLine 3\n"
var lines: [String] = []
sentence.enumerateLines { line, _ in
lines.append(line)
}
print(lines) // "[Line 1, Line 2, Line 3]"
extension String {
var lines: [String] {
var result: [String] = []
enumerateLines { line, _ in result.append(line) }
return result
}
}
用法:
let sentence2 = "Line 4\nLine 5\nLine 6\n"
let sentence2Lines = sentence2.lines
print(sentence2Lines) // ["Line 4", "Line 5", "Line 6"]
let sentence3 = "Line 7\r\nLine 8\r\nLine 9\r\n"
let sentence3Lines = sentence3.lines
print(sentence3Lines) // "[Line 7, Line 8, Line 9]"
答案 1 :(得分:18)
在 Xcode 8.2,Swift 3.0.1:
中使用NSString方法组件(sortedBy:)
let text = "line1\nline2"
let array = text.components(separatedBy: CharacterSet.newlines)
或者使用String方法 enumerateLines ,例如Leo Dabus
的回答
答案 2 :(得分:9)
在Swift 2中,顶级split
函数现在是CollectionType
上的一个方法(每个String
个'字符视图“符合”)。该方法有两个版本,您希望将闭包作为谓词来指示是否应将给定元素视为分隔符。
您可以使用string.utf16
将字符串中的字符集作为UTF16字符集合,使其与NSCharacterSet
API兼容。这样,我们可以在闭包内部轻松检查字符串中的给定字符是否是换行符字符集的成员。
值得注意的是split(_:)
将返回SubSequence
个字符(基本上是Slice
),因此需要转换回字符串数组,这通常更有用。我在下面使用flatMap(String.init)
完成了此操作 - UTF16View
上的String
初始化工具可以使用,因此使用flatMap
将忽略可能返回的任何nil
值,确保您获得一系列非可选字符串。
所以对于一个很好的类似Swift的方式:
let str = "Line 1\nLine 2\r\nLine 3\n"
let newlineChars = NSCharacterSet.newlineCharacterSet()
let lines = str.utf16.split { newlineChars.characterIsMember($0) }.flatMap(String.init)
// lines = ["Line 1", "Line 2", "Line 3"]
这样做的好处是split
方法有一个参数allowEmptySubsequences
,它可以确保您不会在结果中收到任何空字符序列。默认情况下为false
,因此您实际上根本不需要指定它。
如果您想完全避免使用NSCharacterSet
,您可以轻松拆分符合Unicode标准Character
的集合。
let lines = str.characters.split { $0 == "\n" || $0 == "\r\n" }.map(String.init)
Swift能够将"\r\n"
视为单个扩展字形集群,将其用作单个Character
进行比较,而不是创建String
。另请注意,从Character
创建字符串的初始化程序是不可用的,因此我们只能使用map
。
答案 3 :(得分:6)
let test1 = "Line1\n\rLine2\nLine3\rLine4"
let t1 = test1.componentsSeparatedByCharactersInSet(NSCharacterSet.newlineCharacterSet())
let t2 = t1.filter{ $0 != "" }
let t3 = t1.filter{ !$0.isEmpty }
答案 4 :(得分:6)
这个答案是对已经给出的其他解决方案的总结。它来自我的fuller answer,但在这里提供实际的方法选择会很有用。
新行通常使用\n
字符制作,但也可以使用\r\n
制作(来自Windows中保存的文件)。
<强> 1。 componentsSeparatedByCharactersInSet
强>
let multiLineString = "Line 1\nLine 2\r\nLine 3\n"
let newlineChars = NSCharacterSet.newlineCharacterSet()
let lineArray = multiLineString.componentsSeparatedByCharactersInSet(newlineChars).filter{!$0.isEmpty}
// "[Line 1, Line 2, Line 3]"
如果未使用filter
,则\r\n
将生成一个空数组元素,因为它被计为两个字符,因此在同一位置将字符串分隔两次。
<强> 2。 split
强>
let multiLineString = "Line 1\nLine 2\r\nLine 3\n"
let newlineChars = NSCharacterSet.newlineCharacterSet()
let lineArray = multiLineString.utf16.split { newlineChars.characterIsMember($0) }.flatMap(String.init)
// "[Line 1, Line 2, Line 3]"
或
let multiLineString = "Line 1\nLine 2\r\nLine 3\n"
let lineArray = multiLineString.characters.split { $0 == "\n" || $0 == "\r\n" }.map(String.init)
// "[Line 1, Line 2, Line 3]"
此处\r\n
被视为单个Swift字符(扩展字形集群)
第3。 enumerateLines
强>
let multiLineString = "Line 1\nLine 2\r\nLine 3\n"
var lineArray = [String]()
multiLineString.enumerateLines { (line, stop) -> () in
lineArray.append(line)
}
// "[Line 1, Line 2, Line 3]"
有关enumerateLine
语法的详情,请参阅this answer。
\r\n
和\n
,但我这样做是为了表明这些方法可以处理这两种格式。NSCharacterSet.newlineCharacterSet()
是换行符,定义为(U + 000A-U + 000D,U + 0085),其中包括\r
和\n
。答案 5 :(得分:3)
为了记录,Swift的基金会CharacterSet
可以在分割中使用:
extension String {
var lines: [String] {
return split { String($0).rangeOfCharacter(from: .newlines) != nil }.map(String.init)
}
}
extension String {
var lines: [String] {
return split { CharacterSet.newlines.contains($0.unicodeScalars.first!) }.map(String.init)
}
}
答案 6 :(得分:1)
如何在任何换行符处拆分字符串以获取没有任何空元素的String数组?
你几乎就在那里 - 这只是尾随的闭包,这里不同:
let array = stringFromFile.componentsSeparatedByCharactersInSet(NSCharacterSet.newlineCharacterSet()).filter{!$0.isEmpty}
与以下内容相同:
let newLineChars = NSCharacterSet.newlineCharacterSet() // newline characters defined as (U+000A–U+000D, U+0085)
let array = stringFromFile.componentsSeparatedByCharactersInSet(newLineChars).filter{!$0.isEmpty}
ETA:在尾随结束时删除了不必要的额外括号
答案 7 :(得分:0)
Swift 4:
我建议您先将CSV保存到字符串中,如果您还没有完成它,那么&#34;清理&#34;删除不必要的回车的字符串
let dataString = String(data: yourData!, encoding: .utf8)!
var cleanFile = dataString.replacingOccurrences(of: "\r", with: "\n")
cleanFile = cleanFile.replacingOccurrences(of: "\n\n", with: "\n")
上面会给你一个最理想格式的字符串,然后你可以使用\ n作为你的分隔符来分隔字符串:
let csvStrings = cleanFile.components(separatedBy: ["\n"])
现在你有一个包含3个项目的数组:
<强> [&#34;线路1&#34;&#34;线2&#34;&#34;行3&#34;] 强>
我正在使用CSV文件,在执行此操作后,我将项目拆分为组件,因此如果您的项目类似于:
[&#34;线路1,线路2,行3&#34;&#34; LINEA,LineB,LineC&#34;]
let component0 = csvStrings[0].components(separatedBy: [","]) // ["Line1","Line2","Line3"]
let component1 = csvStrings[1].components(separatedBy: [","]) // ["LineA","LineB","LineC"]
答案 8 :(得分:0)
let getName = "Davender+Verma"
let cleanFile = getName.replacingOccurrences(of: "+", with: "+\n")
self.upcomingViewPetName.text = cleanFile
Output: Davender+
verma
Or
let getName = "Davender+Verma"
let cleanFile = getName.replacingOccurrences(of: "+", with: "\n")
self.upcomingViewPetName.text = cleanFile
Output: Davender
verma