最近有人问我这样一个逻辑,应该怎么实现,挺有意思的,就在这里记录一下:
他的需求是这样的:
如上图中(界面太丑,请忽略😅),是一组连续的数据( 当然实际不是这些数字,是其他的一些内容,但是他要记录的只是这些连续的区间,所以无所谓数据内容了).用户自由选择,选中的为红色,最后确定的时候,每个连续的区间形成一个model,记录当前区间的开始索引及长度.
第一感觉是,这挺简单的,就是一个选择排序分组的功能嘛,但是实现起来,还是挺绕的,我简单的做了这么个界面,整体是一个UICollectionView然后实现选中与未选中的状态,下面这是cell的点击方法中,选择数据的逻辑:
let cell = collectionView.cellForItem(at: indexPath) as! LessionCell
let lesson = self.dataSource[indexPath.row]
if lesson.state == .selected {
lesson.state = .unSelected
} else if lesson.state == .unSelected{
lesson.state = .selected
}
cell.lesson = lesson
if self.selected.contains(lesson) {
let index = self.selected.index(of: lesson)
self.selected.remove(at: index!)
} else {
self.selected.append(lesson)
}
等待选择后,下一步就是处理这些选中的数据了,这里的每条数据,我这里定义了一个model:
enum LessonState {
case invalid, busy, unSelected, selected
}
class Lesson: NSObject {
var time: String?
var state: LessonState = .unSelected
}
只是简单的给了一个状态和一个值,记录状态和索引.
最后的处理, 我首先想到的是遍历数组,比较大小,完整的处理逻辑如下:
func btnClick() {
if self.selectedLesson.count > 0 {
self.selectedLesson.removeAll()
}
// 排序
let arr = self.selected.sorted { (first, second) -> Bool in
return Int(first.time!)! < Int(second.time!)!
}
for lesson in arr {
// 输出排序后的数组
print("\(lesson.time)")
}
// 记录当前比较的值的索引
var index: Int = 0
// 当索引小于数组长度时,继续比较
while index < arr.count {
// 取出第一个值
var first = arr[index]
// 取出在大数组中的索引
var index1: Int = self.dataSource.index(of: first)!
// 记录在大数组中的索引
var range = NSRange()
range.location = index1
// 数组索引+1 ,从下一个开始判断
index += 1
for i in index..<arr.count {
// 这里又取一次,是为了for循环内的比较
first = arr[i-1]
// 取出下一个元素
let second = arr[i]
// 比较差值
if Int(second.time!)! - Int(first.time!)! == 1{
// 差值为1,代表连续, 大数组索引+1, 小数组索引+1
index1 += 1
index += 1
} else {
// 当不为1时,不连续,跳出循环
break
}
}
// 一次遍历结束, 创建最终的model
let select = SelectedLesson()
// 计算长度
range.length = index1 - range.location + 1
select.range = range
// 记录选中的连续区间
self.selectedLesson.append(select)
}
print("******************************")
for selec in self.selectedLesson {
print("\(selec.range) + \(selec.range?.location) + \(selec.range?.length)")
}
}
先将选中的数据根据索引进行从小到大排序,然后,遍历排序后的数组.
代码中每一步都有注释,理解起来应该不是问题,这里就不赘述了.
测试上图的选择后输出为:
Optional("13")
Optional("14")
Optional("15")
Optional("25")
Optional("26")
Optional("27")
Optional("38")
******************************
Optional(__C._NSRange) + Optional(13) + Optional(3)
Optional(__C._NSRange) + Optional(25) + Optional(3)
Optional(__C._NSRange) + Optional(38) + Optional(1)