Swiftの配列でmaxを見つける正しい方法


121

これまでのところ、シンプルな(ただし、コストがかかる可能性がある)方法があります。

var myMax = sort(myArray,>)[0]

そして、私が学校でそれをするように教えられた方法:

var myMax = 0
for i in 0..myArray.count {
    if (myArray[i] > myMax){myMax = myArray[i]}
}

Swiftの整数配列から最大値を取得するより良い方法はありますか?Rubyのような1行のものが理想的です.max


あなたは拡張機能を書きます。
gnasher729 2014年

はい、1行:maxElement(myArray)。以下の2番目の答え(ルドルフアダムコビッチ)が現在何であるかを参照してください。
leekaiinthesky


@mattymcgee承認された回答を更新しました。
チャーリーイーガン

回答:


299

与えられた:

let numbers = [1, 2, 3, 4, 5]

スウィフト3:

numbers.min() // equals 1
numbers.max() // equals 5

スウィフト2:

numbers.minElement() // equals 1
numbers.maxElement() // equals 5

2
ComparableオブジェクトでのみNSDecimalNumber機能するため、たとえば機能しません。
ミハウエルナス

2
それは私だけですか、これらの機能はSwift 2に存在しませんか?
Liron Yahdav

@LironYahdav彼らは今メソッドです。修繕。ありがとう!
RudolfAdamkovič2015

2
Swift 3では、これらの名前は単にmin()andに変更されましたmax()
jemmons

1
@Jezzamonいいえ。Swift3では、メソッドはminElementおよびmaxElementに名前が変更さminれましたmax。参照:github.com/apple/swift-evolution/blob/master/proposals/...無料機能するので、私はあなたの混乱を理解minしてmaxも、まだ存在しています。たとえば、gist.github.com
lorentey /

95

更新: Swiftに登場して以来、これはおそらく受け入れられる答えになるはずmaxElementです。


全能の使用reduce

let nums = [1, 6, 3, 9, 4, 6];
let numMax = nums.reduce(Int.min, { max($0, $1) })

同様に:

let numMin = nums.reduce(Int.max, { min($0, $1) })

reduce内部アキュムレータ変数の初期値である最初の値を取得し、渡された関数(ここでは匿名)をアキュムレータと配列の各要素に順次適用し、新しい値をアキュムレータに格納します。その後、最後のアキュムレータ値が返されます。


1
完璧、まさに私が探していたもの。どうやらiBookにはないものがたくさんあります!
チャーリーイーガン2014年

2
これらは単なる一般的な関数型プログラミング手法であり、Swiftに固有のものではありません。
Jean-Philippe Pellet 2014年

10
ジャンPhilippePellet @あなたが実際にだけに、これを簡略化することができますnums.reduce(Int.min, max)ので、maxのプロトタイプはすでにタイプと一致するreduce期待している
drewag

これがdoubleの配列で機能しない理由はありますか?
ニコラス

3
あなただけの関数自体を渡すことができるように、パラメータの署名:最小/最大関数のシグネチャは、組み合わせに一致するlet numMax = nums.reduce(Int.min, combine: max)
レスリー・ゴドウィン

38

スウィフト5と、Arrayその他のようなSequenceプロトコル適合オブジェクト(DictionarySetなど)、2と呼ばれるメソッドがありmax()且つmax(by:)そのリターン最大要素配列またはnil配列が空の場合を。


#1。Arraymax()方法を使用する

あなたのシーケンス準拠の内部要素の型ならばComparableプロトコル(それはかもしれStringFloatCharacterまたはカスタムクラスまたは構造体の1つ)は、使用することができるようになりますmax()次がある宣言を

@warn_unqualified_access func max() -> Element?

シーケンスの最大要素を返します。

次のPlaygroundコードは使用方法を示していますmax()

let intMax = [12, 15, 6].max()
let stringMax = ["bike", "car", "boat"].max()

print(String(describing: intMax)) // prints: Optional(15)
print(String(describing: stringMax)) // prints: Optional("car")
class Route: Comparable, CustomStringConvertible {

    let distance: Int
    var description: String { return "Route with distance: \(distance)" }

    init(distance: Int) {
        self.distance = distance
    }

    static func ==(lhs: Route, rhs: Route) -> Bool {
        return lhs.distance == rhs.distance
    }

    static func <(lhs: Route, rhs: Route) -> Bool {
        return lhs.distance < rhs.distance
    }

}

let routes = [
    Route(distance: 20),
    Route(distance: 30),
    Route(distance: 10)
]

let maxRoute = routes.max()
print(String(describing: maxRoute)) // prints: Optional(Route with distance: 30)

#2。Arraymax(by:)方法を使用する

シーケンス内の要素タイプがComparableプロトコルに準拠していない場合max(by:)は、次の宣言を持つ要素タイプを使用する必要があります。

@warn_unqualified_access func max(by areInIncreasingOrder: (Element, Element) throws -> Bool) rethrows -> Element?

要素間の比較として指定された述語を使用して、シーケンスの最大要素を返します。

次のPlaygroundコードは使用方法を示していますmax(by:)

let dictionary = ["Boat" : 15, "Car" : 20, "Bike" : 40]

let keyMaxElement = dictionary.max(by: { (a, b) -> Bool in
    return a.key < b.key
})

let valueMaxElement = dictionary.max(by: { (a, b) -> Bool in
    return a.value < b.value
})

print(String(describing: keyMaxElement)) // prints: Optional(("Car", 20))
print(String(describing: valueMaxElement)) // prints: Optional(("Bike", 40))
class Route: CustomStringConvertible {

    let distance: Int
    var description: String { return "Route with distance: \(distance)" }

    init(distance: Int) {
        self.distance = distance
    }

}

let routes = [
    Route(distance: 20),
    Route(distance: 30),
    Route(distance: 10)
]

let maxRoute = routes.max(by: { (a, b) -> Bool in
    return a.distance < b.distance
})

print(String(describing: maxRoute)) // prints: Optional(Route with distance: 30)

Swift 3では、「maxElement」は「max」に名前が変更されました
Nicolai Henriksen

16

他の答えはすべて正しいですが、次のようにコレクション演算子を使用することもできます。

var list = [1, 2, 3, 4]
var max: Int = (list as AnyObject).valueForKeyPath("@max.self") as Int

同じ方法で平均を求めることもできます。

var avg: Double = (list as AnyObject).valueForKeyPath("@avg.self") as Double

この構文は他のいくつかのソリューションよりも明確ではないかもしれませんが、-valueForKeyPath:それでもまだ使用できることを確認するのは興味深いです:)


11

で使用できますreduce

let randomNumbers = [4, 7, 1, 9, 6, 5, 6, 9]
let maxNumber = randomNumbers.reduce(randomNumbers[0]) { $0 > $1 ? $0 : $1 } //result is 9


4

Swift 1.2(そしておそらく以前のバージョン)では、以下を使用する必要があります。

let nums = [1, 6, 3, 9, 4, 6];
let numMax = nums.reduce(Int.min, combine: { max($0, $1) })

Double値を操作するために、次のようなものを使用しました。

let nums = [1.3, 6.2, 3.6, 9.7, 4.9, 6.3];
let numMax = nums.reduce(-Double.infinity, combine: { max($0, $1) })

1
これを行うこともできますlet numMax = nums.reduce(-Double.infinity, combine: max)。max関数のシグネチャは、combine:パラメータのシグネチャと一致します。
レスリーゴッドウィン、

3

Swift 2.0では、minElementおよびプロトコルのmaxElementメソッドになるためSequenceType、次のように呼び出す必要があります。

let a = [1, 2, 3]
print(a.maxElement()) //3
print(a.minElement()) //1

maxElementような機能としてmaxElement(a)使用できません

Swiftの構文は流動的であるため、Xcode version7 beta6でこれを確認できます。

将来的に変更される可能性があるため、これらのメソッドを使用する前にドキュメントを確認することをお勧めします。


3

Swift 3.0

このコードはプログラムで試すことができます。

func getSmallAndGreatestNumber() -> Void {

    let numbers = [145, 206, 116, 809, 540, 176]
    var i = 0
    var largest = numbers[0]
    var small = numbers[0]
    while i < numbers.count{

        if (numbers[i] > largest) {
            largest = numbers[i]
        }
        if (numbers[i] < small) {
            small = numbers[i]
        }
        i = i + 1
    }
    print("Maximum Number ====================\(largest)")// 809
    print("Minimum Number ====================\(small)")// 116
}


0

Swift 3/4用に更新:

以下の単純なコード行を使用して、配列から最大値を見つけます。

var num = [11, 2, 7, 5, 21]
var result = num.sorted(){
    $0 > $1
}
print("max from result: \(result[0])") // 21

-1

配列をソートしてから、array.firstまたはを使用することもできますarray.last


5
これは計算的に遅いです。線形時間で最大値を見つけることができます。
チャーリーイーガン

私は非常に新しい@CharlieEganです。線形時間を説明したり、チュートリアルを紹介したりできます。
どうも

「時間の複雑さ」(en.wikipedia.org/wiki/Time_complexity)を読んでください。これも読む価値があります:bigocheatsheet.com。ここにいくつかの優れた例:khanacademy.org/computing/computer-science/algorithms
Charlie Egan
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.