查找数组中最长的字符串

问题描述 投票:0回答:5

我正在尝试找到获取字符串数组中最长字符串的最有效方法。例如:

let array = ["I'm Roi","I'm asking here","Game Of Thrones is just good"]

结果将是 -

"Game Of Thrones is just good"

我尝试过使用

maxElement
函数,但它给出了字母顺序中的最大字符串(
maxElement()
)。

有什么建议吗?谢谢!

swift string sorting max
5个回答
45
投票

不要使用 O(n log(n)) 进行良好排序,而是使用

max(by:)
(数组上的 O(n))为其提供一个闭包来比较字符串长度:

斯威夫特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: {$1.count > $0.count}) {
    print(max)
}

斯威夫特3:

.characters.count
上使用
String
来获取字符串长度:

let array = ["I'm Roi","I'm asking here","Game Of Thrones is just good"]

if let max = array.max(by: {$1.characters.count > $0.characters.count}) {
    print(max)
}

斯威夫特2:

在数组上使用

maxElement
为其提供一个闭包来比较字符串长度:

let array = ["I'm Roi","I'm asking here","Game Of Thrones is just good"]

if let max = array.maxElement({$1.characters.count > $0.characters.count}) {
    print(max)
}

注:

maxElement
O(n)。好的排序是 O(n log(n)),因此对于大型数组,这将比排序快得多。


6
投票

您可以使用

reduce
来执行此操作。它将迭代您的数组,跟踪当前最长的字符串,然后在完成后返回它。

例如:

let array = ["I'm Roi","I'm asking here","Game Of Thrones is just good"]

if let longestString = array.reduce(Optional<String>.None, combine:{$0?.characters.count > $1.characters.count ? $0:$1}) {
    print(longestString) // "Game Of Thrones is just good"
}

(请注意,

Optional.None
现在在 Swift 3 中是
Optional.none

这使用

nil
起始值来解释数组可能为空的事实,正如 @JHZ 所指出的(在这种情况下它将返回
nil
)。如果您知道数组至少有一个元素,则可以将其简化为:

let longestString = array.reduce("") {$0.characters.count > $1.characters.count ? $0:$1}

因为它只迭代每个元素一次,所以它比使用

sort()
更快。我做了一个快速基准测试,
sort()
看起来慢了大约 20 倍(尽管过早优化没有意义,但我觉得值得一提)。


编辑:我建议您使用@vacawama的解决方案,因为它比

reduce
更干净!


3
投票

给你:

let array = ["I'm Roi","I'm asking here","Game Of Thrones is just good"]

var sortedArr = array.sort() { $0.characters.count > $1.characters.count }

let longestEelement = sortedArr[0]

2
投票

@vacawama 是一个很好的选择,但需要考虑的一件事是您可能有多个相同长度的元素。所以:“获取字符串数组中最长的字符串”的结果可能是多个长度相同的String。如果是这样的话,这可能会起作用:

if let max = array.max(by: {$1.count > $0.count}) {
    let largeStrings = array.filter{$0.count == max.count}
    print(largeStrings)
}

1
投票

您还可以通过创建此函数来练习使用泛型:

func longestString<T:Sequence>(from stringsArray: T) -> String where T.Iterator.Element == String{
    return (stringsArray.max {$0.count < $1.count}) ?? ""
}

说明:创建一个名为longestString的函数。声明有一个实现 Sequence 协议的泛型类型 T(Sequence 在这里定义:https://developer.apple.com/documentation/swift/sequence)。 该函数将返回单个字符串(当然是最长的)。 where 子句解释了泛型类型 T 应该限制为具有 String 类型的元素。

在函数内部,通过比较内部元素的最长字符串来调用stringsArray的max函数。 将返回的是最长的字符串(可选,因为如果数组为空,它可以为 nil)。如果最长字符串为零,则(使用 ??)返回一个空字符串作为最长字符串。

现在称呼它:

let longestA = longestString(from:["Shekinah", "Chesedh", "Agape Sophia"])

如果您掌握了使用泛型的窍门,即使字符串隐藏在对象内部,您也可以利用上面的编码模式。您可以将元素更改为同一类的对象(例如 Person)。

因此:

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 {$0.name.count < $1.name.count})?.name ?? ""
}

然后像这样调用函数:

let longestB = longestName(from:[Person(name: "Shekinah"), Person(name: "Chesedh"), Person(name: "Agape Sophia")])

您还可以根据其用途的适当性来重命名您的函数。您可以调整模式以返回其他内容,例如对象本身或字符串的长度(计数)。最后,熟悉泛型可能会提高您的编码能力。

现在,再次稍作调整,您可以进一步扩展,以便可以比较许多不同类型拥有的字符串,只要它们实现通用协议即可。

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 {$0.name.count < $1.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: { $0.count < $1.count }) ?? ""
    }
}

或协议类型:

extension Sequence where Iterator.Element == Nameable {
    func theLongestName() -> Nameable? {
        self.max(by: { $0.name.count < $1.name.count })
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.