如上所述,我编写了一个类,它允许您迭代一组分层数据,同时保持该层次结构有序。您可以通过指定一个或多个根元素(通过数组或可变参数)以及返回给定元素的子元素的闭包来做到这一点。
由于它是作为泛型实现的,如果您知道层次结构是同质的,则可以指定要使用的显式类型,但如果不是,请为该类型指定 Any,然后在闭包中执行逻辑以确定哪个子级输入它。
此外,通过递归实现,不仅以正确的层次顺序返回事物,而且还返回一个级别,以便您知道项目的深度。如果不关心关卡,只需在初始化序列时追加.map{ $0.item }即可直接提取项目。
这是自定义分层序列的代码...
struct HierarchicalSequence<TItem> : Sequence {
typealias GetChildItemsDelegate = (TItem) -> [TItem]?
init(_ rootItems:TItem..., getChildItems: @escaping GetChildItemsDelegate){
self.init(rootItems, getChildItems: getChildItems)
}
init(rootItems:[TItem], getChildItems: @escaping GetChildItemsDelegate){
self.rootItems = rootItems
self.getChildItems = getChildItems
}
let rootItems : [TItem]
let getChildItems : GetChildItemsDelegate
class Iterator : IteratorProtocol {
typealias Element = (level:Int, item:TItem)
init(level:Int, items:[TItem], getChildItems: @escaping GetChildItemsDelegate){
self.level = level
self.items = items
self.getChildItems = getChildItems
}
let level : Int
let items : [TItem]
let getChildItems : GetChildItemsDelegate
private var nextIndex = 0
var childIterator:Iterator?
func next() -> Element? {
// If there's a child iterator, use it to see if there's a 'next' item
if let childIterator = childIterator {
if let childIteratorResult = childIterator.next(){
return childIteratorResult
}
// No more children so let's clear out the iterator
self.childIterator = nil
}
if nextIndex == items.count {
return nil
}
let item = items[nextIndex]
nextIndex += 1
// Set up the child iterator for the next call to 'next' but still return 'item' from this call
if let childItems = getChildItems(item),
childItems.count > 0 {
childIterator = Iterator(
level : level + 1,
items : childItems,
getChildItems : getChildItems)
}
return (level, item)
}
}
func makeIterator() -> Iterator {
return Iterator(level: 0, items: rootItems, getChildItems: getChildItems)
}
}
让我们看一个如何使用它的示例。首先,让我们从一些 JSON 数据开始...
public let jsonString = """
[
{
"name" : "Section A",
"subCategories" : [
{
"name" : "Category A1",
"subCategories" : [
{ "name" : "Component A1a" },
{ "name" : "Component A1b" }
]
},
{
"name" : "Category A2",
"subCategories" : [
{ "name" : "Component A2a" },
{ "name" : "Component A2b" }
]
}
]
},
{
"name" : "Section B",
"subCategories" : [
{
"name" : "Category B1",
"subCategories" : [
{ "name" : "Component B1a" },
{ "name" : "Component B1b" }
]
},
{
"name" : "Category B2",
"subCategories" : [
{ "name" : "Component B2a" },
{ "name" : "Component B2b" }
]
}
]
}
]
"""
这是加载该数据的模型和代码
class Category : Codable {
let name : String
let subCategories : [Category]?
}
public let jsonData = jsonString.data(using: .utf8)!
var rootCategories = try! JSONDecoder().decode([Category].self, from: jsonData)
这是您如何使用序列获取所有类别及其深度...
let allCategoriesWithDepth = HierarchicalSequence(rootItems:rootCategories){ $0.subCategories }
for (depth, category) in allCategoriesWithDepth {
print("\(String(repeating: " ", count: depth * 2))\(depth): \(category.name)")
}
最后,这是输出...
0: Section A
1: Category A1
2: Component A1a
2: Component A1b
1: Category A2
2: Component A2a
2: Component A2b
0: Section B
1: Category B1
2: Component B1a
2: Component B1b
1: Category B2
2: Component B2a
2: Component B2b
享受吧!