iOS Swift:按自定义枚举交替模式排序自定义对象数组
实现自定义对象数组的循环交替排序
这个问题我之前也碰到过!默认的Comparable排序只会把同类型的元素归为一组,完全不符合循环交替的需求。要实现你想要的[movie, tv, trailer, genre, article, movie, tv, trailer, genre, article……]排列,咱们得换个思路:先按类型分组,再按索引轮询从各组取元素,具体步骤如下:
1. 先按目标顺序分组元素
首先,咱们需要把原数组按照指定的类型顺序(.movie→.tv→.trailer→.genre→.article)分成对应的子数组,这样后续可以按顺序轮流取各组的元素。
假设你的自定义对象和枚举是这样的:
// 你的自定义枚举,已经遵循Comparable协议 enum ContentType: Comparable { case movie, tv, trailer, genre, article } // 自定义对象结构 struct ContentItem { let type: ContentType let id: Int // 示例属性,替换成你实际的属性 }
分组的代码可以这么写:
// 示例原数组 let originalItems: [ContentItem] = [ .init(type: .movie, id: 1), .init(type: .movie, id: 2), .init(type: .tv, id: 3), .init(type: .trailer, id: 4), .init(type: .genre, id: 5), .init(type: .article, id: 6), .init(type: .tv, id: 7), .init(type: .genre, id: 8), .init(type: .article, id: 9) ] // 定义咱们想要的交替顺序 let desiredTypeOrder: [ContentType] = [.movie, .tv, .trailer, .genre, .article] // 按类型分组,保持目标顺序 var groupedItems: [ContentType: [ContentItem]] = [:] desiredTypeOrder.forEach { type in groupedItems[type] = originalItems.filter { $0.type == type } }
2. 按索引轮询构建结果数组
接下来,我们需要遍历每个索引(从0开始),依次从每个类型的分组里取出对应索引的元素(如果该分组还有这个索引的元素的话),把它们添加到结果数组中:
var sortedItems: [ContentItem] = [] // 找到所有分组中元素最多的那个的长度,确定需要轮询多少次 let maxGroupCount = groupedItems.values.map { $0.count }.max() ?? 0 for index in 0..<maxGroupCount { // 按目标顺序遍历每个类型 for type in desiredTypeOrder { guard let items = groupedItems[type], index < items.count else { // 如果当前类型的分组没有对应索引的元素,跳过 continue } sortedItems.append(items[index]) } }
运行这段代码后,sortedItems的顺序就是你想要的循环交替模式:[movie(id:1), tv(id:3), trailer(id:4), genre(id:5), article(id:6), movie(id:2), tv(id:7), genre(id:8), article(id:9)]
为什么Comparable排序不行?
你之前用Comparable实现的排序,本质是让同类型的元素根据枚举的rawValue或者你定义的比较规则排在一起,它的逻辑是同类型优先聚合,而不是循环交替取元素,所以肯定达不到你想要的效果。咱们上面的方法是主动控制元素的选取顺序,完美匹配你的需求。
内容的提问来源于stack exchange,提问作者Mike Simz
相关产品推荐
相关产品推荐

