Seems you have found a working solution, but creating a `Dictionary<Range<T>, [T]>` and then convert it to `[Range<T>, Int]` seems to be inefficient.
You can write something like this:
struct GenericDataDistibutor2<T: Comparable & Hashable> {
var data: [T]
var dataRanges: [Range<T>]
var dataBins: [(Range<T>, Int)] {
guard data.count > 0 && dataRanges.count > 0 else {return []} //<- This line may not be needed
return dataRanges.map {r in (r, data.reduce(0) {$0 + (r.contains($1) ? 1 : 0)})}
}
}
Testing code:
var testData = (1...1000).map {_ in Int.random(in: 1...9)}
let ranges = [1..<4, 4..<7, 7..<10]
let distribution = GenericDataDistibutor(data: testData, dataRanges: ranges)
let distribution2 = GenericDataDistibutor2(data: testData, dataRanges: ranges)
for bins in [distribution.dataBins, distribution2.dataBins] {
print("--")
for item in bins {
print(item.0.lowerBound, item.0.upperBound, item.1)
}
}
Output example:
--
1 4 320
4 7 324
7 10 356
--
1 4 320
4 7 324
7 10 356
Some differences.
- Your code may crash, when `data` contains any value out of ranges.
- My code may generate non-sorted `dataBins` when `dataRanges` is not sorted.