LoginSignup
2
4

More than 5 years have passed since last update.

Swift3でgroupBy

Last updated at Posted at 2017-04-22

こんなJSONがあるとして、fruitsTypeごとに集約して、個数を表示したい。
例)
もも 1個
りんご 2個

[
  {
    "fruitsName": "青森産りんご",
    "fruitsType": "りんご"
  },
  {
    "fruitsName": "大都会白桃",
    "fruitsType": "もも"
  },
  {
    "fruitsName": "謎のりんご",
    "fruitsType": "りんご"
  }
]

Array#groupByがあれば簡単にできそうだが、残念ながらSwiftのArrayにはgroupByがない。

extensionで実装

Arrayクラスを拡張して、groupByメソッドを追加する。

class Fruits {
    var fruitsName: String?
    var fruitsType: String?

    init (fruitsName: String?, fruitsType: String?) {
        self.fruitsName = fruitsName
        self.fruitsType = fruitsType
    }
}

extension Array {

    func groupBy<T: Hashable>(_ callback: (Iterator.Element) -> T) -> [T: [Iterator.Element]] {
        var grouped = [T: Array<Iterator.Element>]()

        forEach {
            let key = callback($0)
            if var array = grouped[key] {
                array.append($0)
                grouped[key] = array
            } else {
                grouped[key] = [$0]
            }
        }

        return grouped
    }

}

let fruits = [
    Fruits(fruitsName: "青森産りんご", fruitsType: "りんご"),
    Fruits(fruitsName: "大都会白桃", fruitsType: "もも"),
    Fruits(fruitsName: "謎のりんご", fruitsType: "りんご")
]

fruits.groupBy { $0.fruitsType! }
    .map { "\($0.key) \($0.value.count)個" }
    .forEach { print($0) }

//もも 1個
//りんご 2個

Dollar

だけど、プロジェクトごとにextensionを作成するのは面倒。
そこで、Dollarという、JavaScriptのLodashみたいな関数型プログラミングをサポートするライブラリを導入する。
ExSwiftという、extensionでArrayを拡張するライブラリもあるのだけど、残念ながらSwift3未対応でした

インストール

CocoaPodsでインストールする。Podfileに以下を追記して、pod update

Podfile
pod 'Dollar'

コード

$.groupBy(fruits) { $0.fruitsType! }
    .map { "\($0.key) \($0.value.count)個" }
    .forEach { print($0) }

//もも 1個
//りんご 2個

groupBy以外にも色々便利関数があって、プログラミングが捗りそう。
でもやっぱり、groupByみたいな基本的な関数は公式サポートしてほしいなあ。

2
4
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
4