我有一个名称数组,如下所示。["John Doe","Mary Blog"]
我想做的是处理这个数组,并返回一个首字母如下的数组。
["JD"、"MB"]
我已经完成了这项工作,但我的代码丑陋且效率低下(嵌套循环(。对于像我的例子中这样的小数组来说,这可能很好。
如何更有效地处理阵列?
let contacts = ["John Doe", "Mary Blog"]
var initalsArray: [String] = []
let names = contacts.map {$0}
for name in names {
var initals: String = ""
let fullname = name.components(separatedBy: " ")
for part in fullname {
if part.count > 0 {
initals += part[0]
}
}
initalsArray.append(initals)
}
我没有将其效率与上述答案进行比较,但如果您正在处理names
,使用PersonNameComponentsFormatter
将对您有很大帮助。请查看此处的文档。
在您的情况下,下面的代码提供了所需的输出。
let formatter = PersonNameComponentsFormatter()
let contacts = ["John Doe", "Mary Blog"]
var initalsArray: [String] = []
for contact in contacts {
if let name = formatter.personNameComponents(from: contact) {
formatter.style = .abbreviated
initalsArray.append(formatter.string(from: name))
}
}
output -> ["JD", "MB"]
您必须处理数组中的所有元素。
对于每个元素,必须检测空格并检索下一个字母。
然后,必须使用连接的大写字母构建输出数组。
所以我真的不明白你怎么能避免双重循环。
只有if part.count > 0
是不必要的。
或者,您可以自己扫描字符串以避免生成中间数组fullname
。
您可能也可以通过正则表达式处理来获得结果,但这将是一把大锤。不要。
内部循环的可能实现。(很抱歉,如果这是无效的,我不认识斯威夫特(。
var space: Bool = true
for c in name {
if space && c != ' ' {
initials+= c
}
space= c == ' '
}
请注意,(可选(额外条件c != ' '
可防止出现双空格。
您可以使用map来移除一些自己的循环
let contacts = ["John Doe", "Mary Blog"]
let result = contacts.map { $0.components(separatedBy: .whitespacesAndNewlines).map { String($0.prefix(1)) }.joined(separator: "") }
print(result)
我不知道这是否更快,也许它给了苹果一个机会来进行一些难以进行的优化
实际上,这个答案虽然相似,但可能会更快一点
let contacts = ["John Doe", "Mary Blog"]
let result = contacts.map { $0.components(separatedBy: .whitespacesAndNewlines).reduce("") { $0 + String($1.prefix(1)) } }
print(result)
我只是把它添加到前面的第一个字母的字符串中