iosswiftrealm

Swift Realm "Group By" like android room database


I am using realm in my project and register here category name

I want to list the same categories as one group and write the group numbers next to this list.

This is my Realm database:

import RealmSwift

class CatList: Object {
    @objc dynamic var catname: String = ""
}

I can list data with this code:

let realm = try! Realm()
var Items: Results<CatList>?

override func viewDidLoad() {
    super.viewDidLoad()
    Items = realm.objects(CatList.self)
}

Let's say there are 5 categories in the database

Green

Yellow

Red

Yellow

Green

i have to list the same categories once and print the total number next to it.

So it should be like this;

Green 2
---------
Yellow 2
---------
Red 1

Note: To help, I can do this on android Room as follows.

@Query("Select id, catname, COUNT(catname) AS total FROM catlist GROUP BY catname ORDER BY total DESC")

Sorry for my bad English.


Solution

  • Realm results are homogeneous; they will contain only one type of data. NOTE: See Below Edit!

    Therefore a Realm query will only return one type of object so you can't directly extract both the category name and count at the same time via a Realm query*

    But the solution is pretty straightforward; capture a unique list of categories, iterate over them and output the count of each.

    let results = realm.objects(CatList.self).distinct(by: ["catname"])
    for category in results {
        let cat = category.catname
        let count = realm.objects(CatList.self).where { $0.catname == cat}.count
        print("category: \(cat) has a count of \(count)")
    }
    

    A couple of notes: At this time, it's a good idea to move on to the more modern Realm implementation using @Persisted

    class CatList: Object {
        @Persisted var catname = ""
    }
    

    Also - for readability, since the object isn't a list, it's a single object, CatList could probably be better named Category.

    *The above is a Realm and memory friendly solution handling the data in a lazy-loading fashion. That being said, a one-liner could likely be achieved with Swift High Order functions - however, that's generally not recommended if the dataset is large or of unknown size.

    EDIT: As of Realm 10.51.0 (and a bit before), the AnyRealmValue datatype allows mixed types to be stored within Lists or Maps.

    AnyRealmValue is a Realm property type that can hold different data types. Supported AnyRealmValue data types include (see docs)