如何使用swift简洁地更新高度嵌套的对象模型



我正在编写一个函数,该函数将深入对象层次结构的最深层并更新特定值。作为参考,这就是常规迭代的混乱程度:

func selectedStateUpdated(data: MyObject, tabId: String, rowId: String){
for currIndex in 0..<self.model.data[0].data[0].filters.count{
if(self.model.data[0].data[0].filters[currIndex].headerName == data.headerName){
for tabIdx in 0..<model.data[0].data[0].filters[currIndex].data.count {
if(self.model.data[0].data[0].filters[currIndex].data[tabIdx].id == tabId){
for rowItemIdx in 0..<self.model.data[0].data[0].filters[currIndex].data[tabIdx].data.count {
if(self.model.data[0].data[0].filters[currIndex].data[tabIdx].data[rowItemIdx].id == rowId){
self.model.data[0].data[0].filters[currIndex].data[tabIdx].data[rowItemIdx].isSelected.toggle()
}
}
}
}
}
}
}

深入挖掘数据模型并更新特定属性的最佳方法是什么?我正在尝试将此函数类中的model对象更新为全局对象。考虑到我的对象模型中的可迭代对象在for循环中是不可变的,有没有更好的方法来解决这个问题,同时确保我迭代到正确的中

从本质上讲,这是一个数据结构问题。您正在对所有数据进行线性搜索,以找到具有特定headerNametabIdrowId的数据。它是复杂、混乱和缓慢的(O(headerCount * tabCount * rowCount)!(

如果使用字典,这可能只是:

self.model.data[0].data[0]
.filters[headerName]
.data[tabId]
.data[rowId]
.isSelected
.toggle()

如果数组必须保留,那么可以通过提取命名局部变量的公共部分来大量清理。反转if语句(在本例中,转换为guard语句`(也可以节省大量嵌套:

func selectedStateUpdated(headerName: String, tabId: String, rowId: String){
let data = self.model.data[0].data[0] // TODO: name me better
for currIndex in 0..<data.filters.count {
let filter = data.filters[currIndex]
guard filter.headerName == headerName else { return }
for tabIdx in 0..<filter.data.count {
let tab = filter.data[tabIdx]
guard tab.id == tabId else { continue }
for rowItemIdx in 0..< tab.data.count {
let rowItem = tab.data[rowItemIdx]
guard rowItem.id == rowId else { continue }
self.model.data[0].data[0]
.filters[currIndex]
.data[tabIdx]
.data[rowItemIdx]
.isSelected
.toggle()
}
}
}
}

它可以通过使用zip一次获取索引和项目来进一步改进:

func selectedStateUpdated(headerName: String, tabId: String, rowId: String){
let data = self.model.data[0].data[0] // TODO: name me better
for (currIndex, filter) in zip(data.filters.indices, data.filters) {
guard filter.headerName == headerName else { return }
for (tabIdx, tab) in zip(filter.data.indices, filter.data) {
guard tab.id == tabId else { continue }
for (rowItemIdx, rowItem) in zip(tab.data.indices, tab.data) {
guard rowItem.id == rowId else { continue }
self.model.data[0].data[0]
.filters[currIndex]
.data[tabIdx]
.data[rowItemIdx]
.isSelected
.toggle()
}
}
}
}

基本上,当你说".id==tabId"时,你正在做的是一个过滤函数。这个代码相当混乱。但我想我设法弄明白了:

func selectedStateUpdated(data: [MyObject], tabId: String, rowId: String) {
let filteredResult = self.model.data[0].data[0].filters
.filter({$0.headerName == data.headerName &&
$0.data.filter({$0.id == tabId}) &&
$0.data.filter({$0.id == tabId &&
$0.data.filter({$0.id == rowId})
})
})
if filteredResult.count > 0 {
filteredResult.first!.isSelected.toggle()
}
}

最新更新