Home > OS >  Realm iOS: count the distinct objects in a collection
Realm iOS: count the distinct objects in a collection

Time:05-05

What is the most efficient way to get the count of the unique values on a table?

For example:

fruitType
---------
banana
banana
apple
apple 
apple

bananas : 2 apples : 3

By using fruitsCollection.distinct(by: ["fruitType"]) i can get the distinct values but not the count.

Any help would be appreciated.

CodePudding user response:

you could try something simple like this (assuming fruits are Strings, adjust accordingly to your object types):

let fruits = fruitsCollection.distinct(by: ["fruitType"])
var results = [String:Int]()
Set(fruits).forEach{ fruit in results[fruit] = (fruits.filter{$0 == fruit}).count }
print("---> results: \(results)")

or

let results: [String:Int] = Set(fruits).reduce(into: [:]) { dict, next in
            dict[next] = (fruits.filter{$0 == next}).count }

print("---> results: \(results)")

The Set(fruits) gives you the unique set of fruit names. The filter{...} gives you the count of each. The forEach or the reduce turns the results into a dictionary of key values.

CodePudding user response:

@workingdog answer works very well but here's a more Realmy option. Something to keep in mind is that Realm Results objects are lazily loaded - meaning working with very large datasets has a low memory impact.

However, as soon high level Swift functions are used, that lazy-ness is lost and every object gobbles up memory.

For example, loading 50,000 Realm objects into a Results object doesn't have any significant memory impact - however, loading 50,000 objects into an Array could overwhelm the device as the objects loose their lazy-loading nature.

With this solution, we rely on Realm to present unique values and store them in Results (lazy!) then iterating over those we filter for matching objects (lazy) and return their count.

I created a FruitClass to hold the fruit types

class FruitClass: Object {
    @Persisted var fruitType = ""
}

and then to code

This is a very memory friendly solution

//get the unique types of fruit. results are lazy!
let results = realm.objects(FruitClass.self).distinct(by: ["fruitType"])

//iterate over the results to get each fruit type, and then filter for those to get the count of each
for fruit in results {
    let type = fruit.fruitType
    let count = realm.objects(FruitClass.self).filter("fruitType == %@", type).count
    print("\(type) has a count of \(count)")
}

and the results

apple has a count of 3
banana has a count of 2
orange has a count of 1
pear has a count of 1
  • Related