1. ホーム
  2. ios

Swift の配列で要素の出現回数を数えるには?

2023-08-22 11:54:15

質問

私はこの例をいくつか見ましたが、それらはすべて、どの要素の出現をカウントしたいかを知っていることに依存しているようです。私の配列は動的に生成されるので、私はどの要素の出現をカウントしたいかを知る方法がありません(私はそれらのすべての出現をカウントしたい)。どなたかアドバイスをお願いします。

前もってありがとうございます。

EDIT

もっと明確に言うべきだったかもしれませんが、配列には複数の異なる文字列が含まれます(例えば ["FOO", "FOO", "BAR", "FOOBAR"]

foo、bar、foobarが何であるかを事前に知ることなく、出現回数を数えるにはどうしたらよいでしょうか。

どのように解決するのですか?

Swift 3とSwift 2です。

型の辞書を使用することができます。 [String: Int] の各項目についてカウントを蓄積することができます。 [String] :

let arr = ["FOO", "FOO", "BAR", "FOOBAR"]
var counts: [String: Int] = [:]

for item in arr {
    counts[item] = (counts[item] ?? 0) + 1
}

print(counts)  // "[BAR: 1, FOOBAR: 1, FOO: 2]"

for (key, value) in counts {
    print("\(key) occurs \(value) time(s)")
}

を出力します。

BAR occurs 1 time(s)
FOOBAR occurs 1 time(s)
FOO occurs 2 time(s)


Swift 4です。

スウィフト 4 が導入されました (SE-0165) のような操作で、辞書検索にデフォルト値を含めることができるようになりました。 +=-= のように、です。

counts[item] = (counts[item] ?? 0) + 1

になります。

counts[item, default: 0] += 1

これによって、カウントの操作を簡潔な1行で行うことができます。 forEach :

let arr = ["FOO", "FOO", "BAR", "FOOBAR"]
var counts: [String: Int] = [:]

arr.forEach { counts[$0, default: 0] += 1 }

print(counts)  // "["FOOBAR": 1, "FOO": 2, "BAR": 1]"


Swift 4: reduce(into:_:)

Swift 4 では、新しいバージョンの reduce を使用する新しいバージョンを導入しました。 inout 変数を使用して結果を蓄積します。 これを使うと、カウントの作成が本当に1行になります。

let arr = ["FOO", "FOO", "BAR", "FOOBAR"]
let counts = arr.reduce(into: [:]) { counts, word in counts[word, default: 0] += 1 }

print(counts)  // ["BAR": 1, "FOOBAR": 1, "FOO": 2]

またはデフォルトのパラメータを使用する。

let counts = arr.reduce(into: [:]) { $0[$1, default: 0] += 1 }

最後に、これを Sequence で呼び出せるようにします。 Sequence を含む Hashable を含む項目 Array , ArraySlice , String そして String.SubSequence :

extension Sequence where Element: Hashable {
    var histogram: [Element: Int] {
        return self.reduce(into: [:]) { counts, elem in counts[elem, default: 0] += 1 }
    }
}

このアイデアは この質問 に変更しましたが 計算されたプロパティ . を拡張することを提案してくれた @LeoDabus に感謝します。 Sequence の代わりに Array を使うことで、追加の型を拾うことができます。

print("abacab".histogram)

<ブロッククオート
["a": 3, "b": 2, "c": 1]

print("Hello World!".suffix(6).histogram)

<ブロッククオート
["l": 1, "!": 1, "d": 1, "o": 1, "W": 1, "r": 1]

print([1,2,3,2,1].histogram)

<ブロッククオート
[2: 2, 3: 1, 1: 2]

print([1,2,3,2,1,2,1,3,4,5].prefix(8).histogram)

<ブロッククオート
[1: 3, 2: 3, 3: 2]

print(stride(from: 1, through: 10, by: 2).histogram)

<ブロッククオート
[1: 1, 3: 1, 5: 1, 7: 1, 9: 1]