Takahiro Octopress Blog

-1から始める情弱プログラミング

RealmSwiftでdistinctしよう!

はじめに

今回はRealmSwiftに関するメモ書きです。
RealmSwiftを使って保存したデータをdistinctしたいときがあったのですが、RealmSwift内で定義されているわけではなさそうなので迷いました。
よく考えてみれば、なんてことはなくSwiftに標準で用意されたものを使えばよかったのでした。

distinctする方法

さて、具体的な方法を見てみましょう。
例としてRealmSwiftで保存するオブジェクトを下記のように定義します。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
// Footprint.swift
import Foundation
import RealmSwift

/**
 足跡
 */
class Footprint: Object {
  dynamic var id: Int = 0
  dynamic var title: String = ""
  dynamic var latitude: Double = 0.0
  dynamic var longitude: Double = 0.0
  dynamic var speed: Double = 0.0
  dynamic var direction: Double = 0.0
  dynamic var created: Double = Date().timeIntervalSince1970

  // プライマリーキーの設定
  override static func primaryKey() -> String? {
    return "id"
  }

  // インデックスの設定
  override static func indexedProperties() -> [String] {
    return ["title"]
  }
}

RealmSwiftで保存していくと、下記のような結果になるでしょう。

RealmSwiftブラウザで結果を見てみる

もし、これらのデータからtitledistinctして取得したい場合があったとしましょう。
その場合は下記のように取得します。

1
2
3
4
5
6
7
8
9
10
11
12
// FootprintManager.swift
/**
  保存した足跡タイトルを取得する処理

  - returns: [タイトル]の配列
 */
func distinctByTitle() -> [String] {
  let realm = try! Realm()
  let distinctTitles = Set(realm.objects(Footprint.self).value(forKey: "title") as! [String])

  return distinctTitles
}

実はSwiftではSetという重複を許さない集合体を定義するための型が用意されています。
なので、RealmSwiftから単に取得してきた値をSet型に変換することでdistinctと同じ結果が得られるということになります。

まとめ

さていかがでしたでしょうか。
distinctは決して負荷の軽い処理ではありませんが、様々な場面で求められることでしょう。
使い方を知っておいて損はありません。
ということで今回はメモ書きでした。

Comments