Преобразуйте плоский список в дерево с отсортированными уровнями и отобразите его в виде таблицы, как MacOS Finder - PullRequest
0 голосов
/ 30 ноября 2018

У меня есть плоский список, в котором у каждого элемента есть parentId, а id - это мой код, который преобразует этот список в дерево.

, это класс Node

class Node: DownloadingItemsProvider {
    var children: [Node] = []
    weak var parent: Node?
    var associatedObject: AppListItem?
    var level = 0
    init(associatedObject: AppListItem) {
        self.associatedObject = associatedObject
    }

    func preorder(level: Int = 0) -> [Node] {
        self.level = level
        return [self] + children.flatMap { $0.preorder(level: level + 1) }
    }
}

. Это метод, который преобразуетплоский список из AppListItem в плоский список узлов с правильным упорядочением, с предварительным заказом

func getRootsFrom(list: [AppListItem]) -> [Node] {
    var dict: [String : Node] = [:]
    list.forEach { (appItem) in
        dict[appItem.uuid] = Node(associatedObject: appItem)
    }
    dict.values.forEach { (node) in
        if let value = dict[node.associatedObject?.parentUUID ?? ""] {
            let proposedParent = value
            node.parent = proposedParent
            proposedParent.children.append(node)
            proposedParent.children.sort(by: {$0.associatedObject?.sort ?? "" < $1.associatedObject?.sort ?? ""})
        }
    }
    var roots: [Node] = []
    for root in dict.values.filter({$0.parent == nil}).sorted(by: {$0.associatedObject?.sort ?? "" < $1.associatedObject?.sort ?? ""}) {
        roots.append(contentsOf: root.preorder())
    }

    return roots
} 

Так что в основном у меня есть несколько листов этого дерева, и мне нужно показать поддерево, как приложение Finder, в macOS

вот мое решение

var dataSource: [DownloadingItemsProvider] = []
        let sortedItems = filteredRoot.isEmpty ? root : filteredRoot
        let downloadingListItems = sortedItems.filter { (localItem) -> Bool in
            return downloadingURLItems.contains(where: {$0.key == localItem.associatedObject?.downloadUrl})
        }
        if downloadingListItems.isEmpty {
            return dataSource
        }
        var list: Set<AppListItem> = []

        for item in downloadingListItems {
            for row in getItemsHierachy(for: item.associatedObject?.uuid ?? "") {
                list.insert(row)
            }
        }

        var tempList: [Node] = []
        for item in (filteredRoot.isEmpty ? root : filteredRoot) {
            if let object = item.associatedObject, list.contains(object) {
                tempList.append(item)
                if object.downloadUrl == nil {
                    object.headerTitle = String(repeating: ".", count: item.level) + (object.title ?? "")
                    dataSource.append(item)
                } else {
                    if let downloadObject =  DownloadManager.shared.ongoingDownloads[object.downloadUrl ?? ""]?.object {
                        dataSource.append(downloadObject)
                    }
                }
            }
        }
        _ = configureSize(with: tempList.first?.associatedObject?.parentUUID, listableItems: Dictionary.init(grouping: tempList.map({$0.associatedObject}).compactMap({$0}), by: {$0.parentUUID ?? "root"}), isDownloading: true)
        filteredRoot = tempList
        return dataSource

поэтому сначала я получаю иерархию каждого листа и добавляю это в набор предметов, поэтому в конце у меня есть список всех необходимых предметов, которые нужно показать, но беззная правильное упорядочение, поэтому я делаю цикл for в своем плоском предварительно упорядоченном списке и проверяю, соответствует ли какой-либо элемент любому элементу в моем наборе, и добавляю его в возвращаемый список.Проблема в том, что это работает очень долго для 400 элементов, а также после того, как каждый элемент был загружен или отменен, мне нужно повторно запустить этот код, чтобы получить правильный список, который будет отображаться, поэтому я не понимаю, как приложение Finder работает так быстро, и как онипоказать данные, это простой tableView?

Спасибо в совете.

EDITED

Как я понял, я могу сохранить некоторые для цикла, если яЯ могу создать поддерево из листьев, поэтому мне не нужно делать эту иерархию, и фильтрация

вот что-то, возможно, мне нужно Python (yield): все пути от листьев к корню в дереве

но, к сожалению, я не знаком с Python.

...