My goal is to determine, of all of the currently visible cells in a collection view, which section has the most visible cells.
Start by getting the index paths for the visible cells:
let visible = collectionView.indexPathsForVisibleItems // [IndexPath]
Originally I used an NSCountedSet
followed by mapping and sorting.
let counted = NSCountedSet(array: visible.map { $0.section })
let section = counted.allObjects.map { ($0, counted.count(for: $0)) }.sorted { $0.1 > $1.1 }.first?.0 as? Int
This works but I don't like NSCountedSet
because it deals with Any
.
I then replaced the use of NSCountedSet
with reduce
by reducing the visible array into a dictionary and then using a similar map and sort.
let counted = visible.reduce([Int: Int]()) { (result, path) -> [Int: Int] in
var updated = result
updated[path.section, default: 0] += 1
return updated
}
let section = counted.keys.map { ($0, counted[$0]!) }.sorted { $0.1 > $1.1 }.first?.0
This works as well but I'm hoping there are ways to improve this.
Two main questions:
Can the
reduce
closure be improved? Is there a better way to return the updated dictionary where the keys are section and the values are the count?Once I have the dictionary of sections and counts, is there a better way to find the section with the highest count? Is there something better than mapping to a tuple, sorting those tuples, and finally grabbing the first one?
BTW - If there is a tie for highest count, I don't care which of those sections is returned.