Как я могу кратко обновить вложенную объектную модель, используя swift? - PullRequest
0 голосов
/ 21 апреля 2020

Я пишу функцию, которая углубится в самый глубокий уровень иерархии объектов и обновит определенное значение. Для справки, вот как грязная регулярная итерация оказалась:

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, есть ли лучший способ приблизиться к этому, убедившись, что я итерировал в правильную

Ответы [ 2 ]

0 голосов
/ 21 апреля 2020

В основном то, что вы делаете, когда говорите «.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()
    }
}
0 голосов
/ 21 апреля 2020

По своей сути это проблема структуры данных. Вы выполняете линейный поиск по всем своим данным, чтобы найти что-то с указанием c headerName, tabId, rowId. Это сложно, грязно и медленно (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()
            }
        }
    }
}
...