简体   繁体   English

如何在Swift中按属性类型对数组进行自动排序?

[英]How can I auto-sort an array in Swift by property type?

I'm trying to make a mutating function within a struct that will sort an array by its String property. 我正在尝试在结构中创建一个变异函数,该结构将按其String属性对数组进行排序。 That way, whenever an item is added to the array, it will sort itself alphabetically. 这样,每当将一个项目添加到数组中时,它将按字母顺序对其进行排序。 I realize that what I have right now tries to make a change to the array within the own array's didSet method, but I'm not sure where to go with it right now. 我意识到我现在所拥有的试图在自己的数组的didSet方法中对数组进行更改,但是我不确定现在在哪里使用它。 Currently I'm getting the error "Thread 1: EXC_BAD_ACCESS (code=2, address=...)". 当前,我收到错误“线程1:EXC_BAD_ACCESS(代码= 2,地址= ...)”。 All the other code worked fine before trying to implement the sort method. 在尝试实现sort方法之前,所有其他代码都工作正常。

import Foundation

struct QuoteLibrary {
    var title : String
    var arrayOfSectionTitles: [String]
    var arrayOfSections : [Section] = [] {
        didSet {
            self.configureSections()
        }
    }

    mutating func configureSections() {
        // Sort alphabetically
        arrayOfSections.sort({ $0.title > $1.title })

        let numberOfSections = arrayOfSections.count - 1

        // Update the arrayOfSectionTitles whenever arrayOfSections is set
        var titleArray: [String] = []
        for k in 0...numberOfSections {
            titleArray.append(arrayOfSections[k].title)
        }
        arrayOfSectionTitles = titleArray

        // If a section has no quotes in it, it is removed
        for j in 0...numberOfSections {
            if arrayOfSections[j].arrayOfQuotes.count == 0 {
                arrayOfSections.removeAtIndex(j)
                return
            }
        }

    }
}

struct Section {
    var title : String, arrayOfQuotes:[Quote]
}

struct Quote {
    var section : String, text : String
}

enum QuoteStatus: Int {
    case Unchanged = 0
    case Changed = 1
    case Deleted = 2
    case Added = 3
}

You have a recursion problem. 您有递归问题。 Every time you touch arrayOfSections , it'll call configureSections . 每次触摸arrayOfSections ,它将调用configureSections That includes the changes configureSections is making to arrayOfSections , such as sorting or removing empty sections. 其中包括 configureSectionsarrayOfSections的更改,例如对空白部分进行排序或删除。 You might just about get away with it with the removing of empty sections (because after the removal, the subsequent call doesn't remove anything, so won't alter the array and re-call the function), but sorting it pushed things over the edge. 您可能只是通过删除空部分来摆脱它(因为在删除之后,后续调用不会删除任何内容,因此不会更改数组并重新调用该函数),但是对它进行排序会使事情结束边缘。

You would probably be better off with a private array, and then a computed property that provided access to it, like this: 您最好使用私有数组,然后再使用提供对其访问权限的计算属性,如下所示:

struct QuoteLibrary {
    private var _arrayOfSections: [Section] = []

    var title: String
    var arrayOfSectionTitles: [String] = []

    var arrayOfSections: [Section] {
        get { return _arrayOfSections }
        set(newArray) {
            _arrayOfSections = newArray.filter { !$0.arrayOfQuotes.isEmpty }
            _arrayOfSections.sort { $0.title > $1.title }
            arrayOfSectionTitles = _arrayOfSections.map { $0.title }
        }
    }

    init(title: String) { self.title = title }
}

Also you definitely want to look into Swift's capabilities for mapping, filtering of arrays etc. as an alternative to your for loops. 另外,您当然想研究Swift的映射,数组过滤等功能,以替代for循环。 Especially with your remove loop – removing elements from an array as you're iterating over it is really quite tricky, filter is a lot less error prone. 特别是在您的remove循环中–在迭代数组时从数组中删除元素确实非常棘手, filter出错率要低得多。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM