SwiftのカスタムクラスArrayでユニーク値
SwiftのArray内に以下の様なクラスのオブジェクトが入っていたとして、プロパティの値のユニーク一覧を取得するときのメモ。
※末尾にNSArrayでの記法も書いておきます。
(NSArrayのvalueForKeyPath:メソッドは非常に有難いです)
使用するカスタムクラス(!無しのプロパティに修正)
Cat.swift
class Cat:NSObject{
var name:String
var color:String
var age:Int
var score:Int
init(data: (String,String,Int,Int)){
name = data.0
color = data.1
age = data.2
score = data.3
}
}
テストデータ
テストデータを準備しておきます。
UseCat.swift
var all_cats:[Cat] = [Cat]()
all_cats.append(Cat(data:("タマ","白",10,10)))
all_cats.append(Cat(data:("コトロ","茶トラ",2,10)))
all_cats.append(Cat(data:("ミケ","三毛",3,10)))
all_cats.append(Cat(data:("チビトラ","茶トラ",4,10)))
all_cats.append(Cat(data:("タケチヨ","キジトラ",7,10)))
all_cats.append(Cat(data:("マリアンヌ","白",7,10)))
ユニークな値を取るには
正直いい方法が見つからなかったので、filterとreduceを組み合わせてみました。
(もっといい方法がありましたらぜひ教えて下さい)
【やり方】
・reduceの引数(=戻り値)をtemp:Arrayにして、そこに重複しない値をappendする
UseCat.swift
var cat_colors = all_cats.reduce([String](),{
//引数省略の$0はそのままではreturnできないので、変数に代入
var temp = $0
//存在チェックで使用したい値を変数に確保
let color = $1.color
//戻り値の配列arrayに対して、カテゴリ値でフィルター件数を取得
let count:Int = temp.filter({
$0 == color
}).count
//まだ存在していなければ、追加
if count==0 { temp.append($1.color) }
return temp
})
//結果確認
println(cat_colors)
【実行結果】
[白, 茶トラ, 三毛, キジトラ]
Objective-Cと同様にNSArrayを使う場合
NSArrayのvalueForKeyPathというメソッドは非常に高機能で、このようにユニークだけでなく最大最小、平均、合計なども簡単に処理することができます。
Swiftで利用するときには、配列をNSArrayでキャストすることと、戻り値となるArrayの型を明記することが大切です。
UseCat.swift
let cat_colors2
= (all_cats as NSArray).valueForKeyPath("@distinctUnionOfObjects.color")
as [String]
println(cat_colors2)
【実行結果】
[白, 茶トラ, 三毛, キジトラ]