Swift:嵌套循环的高效解决方案

时间:2020-03-18 04:13:38

标签: ios swift xcode performance uitableview

我正在寻找一种更有效的解决方案,以在Swift中详尽地比较同一数组的对象与每个对象。嵌套for-in循环非常详尽,简单,并且返回正确的结果,但是时间复杂度为O(n ^ 2),在性能和更大的数据集方面,没有人建议这样做。我寻找了很长时间的解决方案,然后才发现有人将for-in循环场景描述为二次时间复杂度的经典示例。帮助吗?

编辑(现在包括func tableView(tableView:cellForRowAt :)代码):

好吧,根据要求深入了解。

考虑一下UITableView,其中有一个Event对象数组。

Event是一个类,您想详尽地检查数组的Event对象是否相互冲突。

该数组已按每个Event元素的startTike属性按时间顺序排序。可能会有重复的事件,因为用户可能希望这样做(知道原因,但这是最终用户的选择)。

每个事件对象都有此检查的DateInterval属性。

如果发现冲突,则需要运行逻辑以评估冲突。

如果满足某些条件,则可以在Event对象上设置一个布尔属性(isConflicted)。

然后,将所得数组用于将indexPath.row特定的Event对象传递到自定义UITableViewCell,以在UITableView中进行展示,其中“ isConflicted”布尔值是UITableViewCell的布局/演示所不可缺少的。

尽管运行时复杂度不是很高,但这里的嵌套循环解决方案我工作得很好。

很抱歉,没有更早地包含代码。我错误地认为没有必要。

override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {

    // unwrap my custom cell
    guard let cell = tableView.dequeueReusableCell(withIdentifier: "eventCell", for: indexPath) as? EventDetailTableViewCell else {

        return UITableViewCell()
    }

    // get the relevant section's events array from EventModelController.shared.groupedEventsDictionary check for nil

    guard let events = EventModelController.shared.groupedEventsDictionary[sections[indexPath.section]] else {

        print("ERROR: no event value found in EventModelController.shared.groupedEventsDictionary[sections[indexPath.section]] in EventsTableViewController.swift -> tableView(cellForRowAt:) - line 117.")

        return UITableViewCell()
    }


    var eventDictionary: [DateInterval : Event] = [:]

    for event in events {

        eventDictionary[event.dateInterval] = event

    }

    // START: - option with time complexity O(n^2) that always works
    // check the array for conflicts and set relevant event's isConflicted property
    for event in events {

        for anotherEvent in events {

            // ensure that we don't redundantly check the same events against themselves
            if event != anotherEvent {

                if event.dateInterval.intersects(anotherEvent.dateInterval) {

                    if event.stopTime == anotherEvent.startTime || event.startTime == anotherEvent.stopTime {

                        event.isConflicted = false

                    } else {

                        event.isConflicted = true
                    }
                }
            }
        }
    }
    // END: - option with time complexity O(n^2) that always works

    // Configure the cell...
    cell.event = events[indexPath.row]

    return cell
}

1 个答案:

答案 0 :(得分:0)

有一个建议。

extension Array where Element: Hashable {
    var containsDouplicated: Bool {
        Set<Element>.init(self).count < self.count
    }
}

我创建此扩展是为了使用Set的功能来消除重复的值,然后我检查了set(仅具有唯一值)是否具有相同数量的元素。 我认为这是O(2n),所以O(n)。

有一个使用方法的示例。

let a1 = [1,2,3]
let a2 = [1,2,3,4,1]

a1.containsDouplicated // false
a2.containsDouplicated // true

extension Array where Element: Hashable {
    var containsDouplicated: Bool {
        Set<Element>.init(self).count < self.count
    }
}

编辑:编辑后,我建议您制作Event : Hashable并实施一种:

extension Array where Element: Hashable {
    var containsDouplicates: Bool {
        Set<Element>.init(self).count < self.count
    }

    var orderedUniqueElements: [Element] {
        var uniq: Set<Element> = .init(self)
        let filtered: [Element] = self.filter { element -> Bool in
            if !uniq.contains(element) {
                return false
            } else {
                uniq.remove(element)
            }
            return true
        }

        return filtered
    }
}

为了保留indexPath。