如何将CoreData的NSSet按列行转换为有序二维数组?
解决方案
1. 转换NSSet为Swift数组
NSSet是无序集合,先转成强类型数组便于后续操作:
let elements = coreDataNSSet.allObjects as! [Element]
2. 按列分组并排序组内元素
用Dictionary(grouping:)按column属性分组,同时对每个分组内的元素按row升序排序:
// 按column完成分组 var columnGroups = Dictionary(grouping: elements) { $0.column } // 对每个分组的元素按row从小到大排序 columnGroups.forEach { column, group in columnGroups[column] = group.sorted { $0.row < $1.row } }
3. 构建有序二维数组(处理列空缺)
字典的键是无序的,所以要先确定列的范围,遍历从最小到最大的column值,保证外层数组的列顺序正确,同时处理无元素的列:
guard let minCol = elements.min(by: { $0.column < $1.column })?.column, let maxCol = elements.max(by: { $0.column < $1.column })?.column else { return [] // 无元素时返回空数组 } var finalArray = [[Element]]() for col in minCol...maxCol { // 该列有元素则添加排序后的数组,无元素则添加空数组 finalArray.append(columnGroups[col] ?? []) }
可选:处理行空缺(用nil占位)
如果需要同一列内按row顺序排列,空缺的row位置用nil填充(比如row 0有值、row 1空缺、row 2有值时,内层数组为[elem0, nil, elem2]),可以使用这段代码:
var arrayWithNilPlaceholders = [[Element?]]() for col in minCol...maxCol { guard let group = columnGroups[col] else { arrayWithNilPlaceholders.append([]) continue } let minRow = group.min(by: { $0.row < $1.row })!.row let maxRow = group.max(by: { $0.row < $1.row })!.row // 初始化对应长度的数组,默认填充nil var rowArray = [Element?](repeating: nil, count: Int(maxRow - minRow + 1)) // 将元素放到对应row的索引位置 group.forEach { elem in let index = Int(elem.row - minRow) rowArray[index] = elem } arrayWithNilPlaceholders.append(rowArray) }
你之前尝试失败的可能原因
- 未处理字典键的无序性:
Dictionary(grouping:)生成的字典是无序的,直接转数组会导致列顺序混乱,必须手动遍历连续的column范围。 - 组内元素未排序:分组后没有对每个组的元素按
row属性排序。 - 忽略了列空缺:跳过了没有元素的列,导致二维数组的结构不完整。
内容的提问来源于stack exchange,提问作者Vincent
相关产品推荐
相关产品推荐

