2016-07-16 5 views
4

私は配列の番号を持っていますが、この配列で最も頻繁に番号を知りたいと思います。配列には5〜6個の整数があり、時には10〜12個、時にはそれ以上の数もあります。配列内の整数も異なっていてもかまいません。ですから、配列の長さと値を変えて機能する関数が必要です。スイフト3:配列の最も頻繁な値を取得する

一例:

myArray = [0, 0, 0, 1, 1] 

もう一つの例:それは3倍であるよう

myArray = [4, 4, 4, 3, 3, 3, 4, 6, 6, 5, 5, 2] 

は、今私は、Integerとして(最初の例では)0を与える関数を探していますこの配列と配列(1)内の他の整数は配列内で2回だけです。または、2番目の例では4となります。

これは簡単な方法ですが、解決策が見つかりません。ソリューションが辞書を使って作業する場合、または解決方法が単純な場合、Webでいくつかの例が見つかりましたが、Swift 3では使用できません...

しかし、私。誰かが、整数の配列でもっとも頻繁な整数を取得する方法を知っていますか?

ありがとうございます。

+0

'for'よりも簡潔なものについては、' map'と他の高次関数を見てください。 –

答えて

13
let myArray = [4, 4, 4, 3, 3, 3, 4, 6, 6, 5, 5, 2] 

// Create dictionary to map value to count 
var counts = [Int: Int]() 

// Count the values with using forEach  
myArray.forEach { counts[$0] = (counts[$0] ?? 0) + 1 } 

// Find the most frequent value and its count with max(isOrderedBefore:)  
if let (value, count) = counts.max(isOrderedBefore: {$0.1 < $1.1}) { 
    print("\(value) occurs \(count) times") 
} 

出力:

4 occurs 4 times 

ここでは、関数として次のとおりです。

func mostFrequent(array: [Int]) -> (value: Int, count: Int)? { 
    var counts = [Int: Int]() 

    array.forEach { counts[$0] = (counts[$0] ?? 0) + 1 } 

    if let (value, count) = counts.max(isOrderedBefore: {$0.1 < $1.1}) { 
     return (value, count) 
    } 

    // array was empty 
    return nil 
} 

if let result = mostFrequent(array: [1, 3, 2, 1, 1, 4, 5]) { 
    print("\(result.value) occurs \(result.count) times")  
} 
1 occurs 3 times 
+0

作品、ありがとう、私の友人!私はうまくいかないようなものを見つけましたが、これは素晴らしい作品です。 – aignetti

+0

@vacawama myArrayにCGPointがあった場合、どのように動作しますか?私はエラー 'タイプ' CGPoint 'プロトコル' Hashable'' – Hilarious404

+0

@ Hilarious404に準拠していないエラーを取得しています、私はあなたがすでに新しい質問ですので、良いアイデアです、新しい質問を参照してください参照してください。私はCGPoint Hashableを作る方法を提案しようとしていましたが、これはMartinRの投稿がしているものです。私はそれを試してみることをお勧めします。 – vacawama

6

最も頻繁に使用される値を「モード」といいます。

let mode = myArray.reduce([Int: Int]()) { 
    var counts = $0  
    counts[$1] = ($0[$1] ?? 0) + 1 
    return counts 
}.max { $0.1 < $1.1 }?.0 

「読み取り不可能」または「エレガント」とみなされるかどうかは、高次機能に対するユーザーの気持ちによって異なります。それにもかかわらず、ここでは(それがどんなHashable要素型で動作します)Arrayの延長では一般的な方法として、次のとおりです。

extension Array where Element: Hashable { 
    var mode: Element? { 
     return self.reduce([Element: Int]()) { 
      var counts = $0 
      counts[$1] = ($0[$1] ?? 0) + 1 
      return counts 
     }.max { $0.1 < $1.1 }?.0 
    } 
} 

あなたではなく、カウントを含んでタプルを持っていると思います場合は単に.0を削除しますモードの。

+2

私は高次関数が非常にエレガントであると信じています。 ';'を使ってできるだけ多くのものをできるだけたくさん隠すようにしてください。私は可読性を高めるためにあなたの答えを編集し、それがライン外にあると感じたら編集を逆にします。 (解決のための+1は、以前のフォーマットにのみ適用されます:) – dfri

+0

@ andyvn22 myArrayがCGPointsを持っていた場合、これはどのように機能しますか? 'Type 'CGPointがプロトコル' Hashable 'に従っていないというエラーが出ています – Hilarious404

+0

@ Hilarious404これは本当に別の質問です。' CGPoint'を拡張して 'Hashable'適合性を追加する必要があります。 – andyvn22

14

ます。またNSCountedSetを使用することができ、ここでのコードは、以下のコメントでスマートな提案を@Benモローへ

let nums = [4, 4, 4, 3, 3, 3, 4, 6, 6, 5, 5, 2] 
let countedSet = NSCountedSet(array: nums) 
let mostFrequent = countedSet.max { countedSet.count(for: $0) < countedSet.count(for: $1) } 

おかげです。

+2

ありがとう!今までCountedSetについて知りませんでした。素晴らしいヒント。 :-) – aignetti

+1

@appzYourLife less than比較の両方の要素が '$ 0.0'である理由を説明できますか?私はそれらが '$ 0'と' $ 1 'であると期待します。これは 'max(by:)'のヘッダファイルの例です:let hues = ["Heliotrope":296、 "Coral":16、 "Aquamarine":156]; let the bestHue = hues.max {a、a.value

+0

@BenMorrow:私の間違い、あなたのヒントをありがとう。 –

関連する問題