There has got to be a more expressive way to do this using map
, filter
, reduce
and friends.
Background:
The categories
property is an [Category]?
, where each element has a videos
property of type [Video]
.
I'm trying to find the index path for video
.
var indexPath: NSIndexPath?
for var i = 0; i < categories?.count ; ++i {
for var j = 0; j < categories?[i].videos.count ; ++j {
if categories?[i].videos[j] == video {
indexPath = NSIndexPath(forRow: j, inSection: i)
}
}
}
if let indexPath = indexPath {
tableView.reloadRowsAtIndexPaths([ indexPath ], withRowAnimation: UITableViewRowAnimation.Automatic)
}
A possible solution (written in Swift 2):
let indexPaths = categories?.enumerate().flatMap() { (section, aCategory) in
aCategory.videos.enumerate().filter() { (_, aVideo) in
aVideo == video
}.map { (row, _) in
NSIndexPath(forRow: row, inSection: section)
}
} ?? []
indexPaths
is an array of all matching index paths (or an empty array). If you don't need/like that, use
let indexPath = categories?.enumerate().flatMap() { (section, aCategory) in
aCategory.videos.enumerate().filter() { (_, aVideo) in
aVideo == video
}.map { (row, _) in
NSIndexPath(forRow: row, inSection: section)
}
}.first
instead, which is an optional index path.
categories?.enumerate()
is a sequence of (section, aCategory)
pairs. For each category, aCategory.videos.enumerate()
is a
sequence of (row, aVideo)
pairs. This sequence is filtered
according to the search term, and the filtered pairs are mapped
to an index path.
So the result of the transform passed to flatMap()
is an array
of index paths of the matching items, one array for each category.
flatMap()
joins these to a single array.
In Swift 1.2 this would be
let indexPaths = flatMap(enumerate(categories ?? [])) { (section, aCategory) in
filter(enumerate(aCategory.videos)) { (_, aVideo) in
aVideo == video
}.map { (row, _) in
NSIndexPath(forRow: row, inSection: section)
}
}