Swift - 在 [String] 数组中查找最长字符串的最佳实践
Swift - best practice to find the longest string at [String] array
我正在寻找获取字符串数组中最长字符串的最有效方法。例如:
let array = ["I'm Roi","I'm asking here","Game Of Thrones is just good"]
结果将是 - "Game Of Thrones is just good"
我试过使用 maxElement
函数,它给出了字母顺序中的最大字符串 (maxElement()
)。
有什么建议吗?谢谢!
您可以使用 reduce
来做到这一点。它将遍历您的数组,跟踪当前最长的字符串,然后在完成后 return 它。
例如:
let array = ["I'm Roi","I'm asking here","Game Of Thrones is just good"]
if let longestString = array.reduce(Optional<String>.None, combine:{[=10=]?.characters.count > .characters.count ? [=10=]:}) {
print(longestString) // "Game Of Thrones is just good"
}
(注意 Optional.None
现在是 Swift 3 中的 Optional.none
)
这使用 nil
起始值来说明数组可能为空的事实,正如@JHZ 所指出的(在这种情况下它将 return nil
) .如果你知道你的数组至少有一个元素,你可以将它简化为:
let longestString = array.reduce("") {[=11=].characters.count > .characters.count ? [=11=]:}
因为它只遍历每个元素一次,所以比使用 sort()
更快。我做了一个快速基准测试,sort()
看起来慢了大约 20 倍(虽然过早优化没有意义,但我觉得值得一提)。
编辑: 我建议您使用@vacawama 的解决方案,因为它比 reduce
!
更干净
给你:
let array = ["I'm Roi","I'm asking here","Game Of Thrones is just good"]
var sortedArr = array.sort() { [=10=].characters.count > .characters.count }
let longestEelement = sortedArr[0]
不要使用 O(n log(n)) 的排序,而是使用 max(by:)
,即 O(n) 在 Array 上提供闭包来比较字符串长度:
Swift 4:
对于 Swift 4 你可以用 count
属性 在 String
:
上得到字符串长度
let array = ["I'm Roi","I'm asking here","Game Of Thrones is just good"]
if let max = array.max(by: {.count > [=10=].count}) {
print(max)
}
Swift 3:
在 String
上使用 .characters.count
获取字符串长度:
let array = ["I'm Roi","I'm asking here","Game Of Thrones is just good"]
if let max = array.max(by: {.characters.count > [=11=].characters.count}) {
print(max)
}
Swift 2:
在 Array 上使用 maxElement
,为其提供一个闭包来比较字符串长度:
let array = ["I'm Roi","I'm asking here","Game Of Thrones is just good"]
if let max = array.maxElement({.characters.count > [=12=].characters.count}) {
print(max)
}
注:maxElement
是O(n)。一个好的排序是 O(n log(n)),所以对于大型数组,这将比排序快得多。
您还可以通过创建此函数来练习泛型的使用:
func longestString<T:Sequence>(from stringsArray: T) -> String where T.Iterator.Element == String{
return (stringsArray.max {[=10=].count < .count}) ?? ""
}
解释:创建一个名为 longestString 的函数。声明有一个泛型类型 T 实现了 Sequence 协议(这里定义了 Sequence:https://developer.apple.com/documentation/swift/sequence)。该函数将 return 单个字符串(当然是最长的)。 where 子句说明泛型类型 T 应限于具有 String 类型的元素。
函数内部,通过比较里面元素的最长字符串,调用stringsArray的max函数。 returned 是最长的字符串(一个可选的,因为如果数组为空,它可以是 nil)。如果最长的字符串为 nil,则(使用 ??)returns 一个空字符串作为最长的字符串。
现在称呼它:
let longestA = longestString(from:["Shekinah", "Chesedh", "Agape Sophia"])
如果您掌握了使用泛型的诀窍,即使字符串隐藏在对象中,您也可以使用上面的编码模式。您可以将元素更改为相同 class(例如人)的对象。
因此:
class Person {
let name: String
init(name: String){
self.name = name
}
}
func longestName<T:Sequence>(from stringsArray: T) -> String where T.Iterator.Element == Person{
return (stringsArray.max {[=12=].name.count < .name.count})?.name ?? ""
}
然后像这样调用函数:
let longestB = longestName(from:[Person(name: "Shekinah"), Person(name: "Chesedh"), Person(name: "Agape Sophia")])
您还可以根据功能的适用性重命名您的功能。您可以将模式调整为 return 其他内容,例如对象本身或字符串的长度(计数)。最后,熟悉泛型可能会提高您的编码能力。
现在,再次稍作调整,您可以进一步扩展,以便您可以比较许多不同类型拥有的字符串,只要它们实现了通用协议即可。
protocol Nameable {
var name: String {get}
}
这定义了一个名为 Nameable 的协议,它要求实施者拥有一个 String 类型的名称变量。接下来,我们定义两个不同的东西来实现协议。
class Person: Nameable {
let name: String
init(name: String){
self.name = name
}
}
struct Pet: Nameable {
let name: String
}
然后我们调整我们的通用函数,使其要求元素必须符合 Nameable,尽管它们有很大的不同。
func longestName<T:Sequence>(from stringsArray: T) -> String where T.Iterator.Element == Nameable{
return (stringsArray.max {[=16=].name.count < .name.count})?.name ?? ""
}
让我们将不同的对象收集到一个数组中。然后调用我们的函数。
let myFriends: [Nameable] = [Pet(name: "Bailey"), Person(name: "Agape Sophia")]
let longestC = longestName(from: myFriends)
最后,在了解上面的“where”和上面的“Sequence”之后,您可以简单地扩展 Sequence:
extension Sequence where Iterator.Element == String {
func topString() -> String {
self.max(by: { [=18=].count < .count }) ?? ""
}
}
或协议类型:
extension Sequence where Iterator.Element == Nameable {
func theLongestName() -> Nameable? {
self.max(by: { [=19=].name.count < .name.count })
}
}
我正在寻找获取字符串数组中最长字符串的最有效方法。例如:
let array = ["I'm Roi","I'm asking here","Game Of Thrones is just good"]
结果将是 - "Game Of Thrones is just good"
我试过使用 maxElement
函数,它给出了字母顺序中的最大字符串 (maxElement()
)。
有什么建议吗?谢谢!
您可以使用 reduce
来做到这一点。它将遍历您的数组,跟踪当前最长的字符串,然后在完成后 return 它。
例如:
let array = ["I'm Roi","I'm asking here","Game Of Thrones is just good"]
if let longestString = array.reduce(Optional<String>.None, combine:{[=10=]?.characters.count > .characters.count ? [=10=]:}) {
print(longestString) // "Game Of Thrones is just good"
}
(注意 Optional.None
现在是 Swift 3 中的 Optional.none
)
这使用 nil
起始值来说明数组可能为空的事实,正如@JHZ 所指出的(在这种情况下它将 return nil
) .如果你知道你的数组至少有一个元素,你可以将它简化为:
let longestString = array.reduce("") {[=11=].characters.count > .characters.count ? [=11=]:}
因为它只遍历每个元素一次,所以比使用 sort()
更快。我做了一个快速基准测试,sort()
看起来慢了大约 20 倍(虽然过早优化没有意义,但我觉得值得一提)。
编辑: 我建议您使用@vacawama 的解决方案,因为它比 reduce
!
给你:
let array = ["I'm Roi","I'm asking here","Game Of Thrones is just good"]
var sortedArr = array.sort() { [=10=].characters.count > .characters.count }
let longestEelement = sortedArr[0]
不要使用 O(n log(n)) 的排序,而是使用 max(by:)
,即 O(n) 在 Array 上提供闭包来比较字符串长度:
Swift 4:
对于 Swift 4 你可以用 count
属性 在 String
:
let array = ["I'm Roi","I'm asking here","Game Of Thrones is just good"]
if let max = array.max(by: {.count > [=10=].count}) {
print(max)
}
Swift 3:
在 String
上使用 .characters.count
获取字符串长度:
let array = ["I'm Roi","I'm asking here","Game Of Thrones is just good"]
if let max = array.max(by: {.characters.count > [=11=].characters.count}) {
print(max)
}
Swift 2:
在 Array 上使用 maxElement
,为其提供一个闭包来比较字符串长度:
let array = ["I'm Roi","I'm asking here","Game Of Thrones is just good"]
if let max = array.maxElement({.characters.count > [=12=].characters.count}) {
print(max)
}
注:maxElement
是O(n)。一个好的排序是 O(n log(n)),所以对于大型数组,这将比排序快得多。
您还可以通过创建此函数来练习泛型的使用:
func longestString<T:Sequence>(from stringsArray: T) -> String where T.Iterator.Element == String{
return (stringsArray.max {[=10=].count < .count}) ?? ""
}
解释:创建一个名为 longestString 的函数。声明有一个泛型类型 T 实现了 Sequence 协议(这里定义了 Sequence:https://developer.apple.com/documentation/swift/sequence)。该函数将 return 单个字符串(当然是最长的)。 where 子句说明泛型类型 T 应限于具有 String 类型的元素。
函数内部,通过比较里面元素的最长字符串,调用stringsArray的max函数。 returned 是最长的字符串(一个可选的,因为如果数组为空,它可以是 nil)。如果最长的字符串为 nil,则(使用 ??)returns 一个空字符串作为最长的字符串。
现在称呼它:
let longestA = longestString(from:["Shekinah", "Chesedh", "Agape Sophia"])
如果您掌握了使用泛型的诀窍,即使字符串隐藏在对象中,您也可以使用上面的编码模式。您可以将元素更改为相同 class(例如人)的对象。
因此:
class Person {
let name: String
init(name: String){
self.name = name
}
}
func longestName<T:Sequence>(from stringsArray: T) -> String where T.Iterator.Element == Person{
return (stringsArray.max {[=12=].name.count < .name.count})?.name ?? ""
}
然后像这样调用函数:
let longestB = longestName(from:[Person(name: "Shekinah"), Person(name: "Chesedh"), Person(name: "Agape Sophia")])
您还可以根据功能的适用性重命名您的功能。您可以将模式调整为 return 其他内容,例如对象本身或字符串的长度(计数)。最后,熟悉泛型可能会提高您的编码能力。
现在,再次稍作调整,您可以进一步扩展,以便您可以比较许多不同类型拥有的字符串,只要它们实现了通用协议即可。
protocol Nameable {
var name: String {get}
}
这定义了一个名为 Nameable 的协议,它要求实施者拥有一个 String 类型的名称变量。接下来,我们定义两个不同的东西来实现协议。
class Person: Nameable {
let name: String
init(name: String){
self.name = name
}
}
struct Pet: Nameable {
let name: String
}
然后我们调整我们的通用函数,使其要求元素必须符合 Nameable,尽管它们有很大的不同。
func longestName<T:Sequence>(from stringsArray: T) -> String where T.Iterator.Element == Nameable{
return (stringsArray.max {[=16=].name.count < .name.count})?.name ?? ""
}
让我们将不同的对象收集到一个数组中。然后调用我们的函数。
let myFriends: [Nameable] = [Pet(name: "Bailey"), Person(name: "Agape Sophia")]
let longestC = longestName(from: myFriends)
最后,在了解上面的“where”和上面的“Sequence”之后,您可以简单地扩展 Sequence:
extension Sequence where Iterator.Element == String {
func topString() -> String {
self.max(by: { [=18=].count < .count }) ?? ""
}
}
或协议类型:
extension Sequence where Iterator.Element == Nameable {
func theLongestName() -> Nameable? {
self.max(by: { [=19=].name.count < .name.count })
}
}