こんな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みたいな基本的な関数は公式サポートしてほしいなあ。