简体   繁体   English

如何在Swift中使用两种对象对数组进行排序?

[英]How can I sort array with two kind of objects in Swift?

This is my method when I sort elements by position property. 这是我按position属性对元素排序时的方法。 Both DBSet and DBItem have that property. DBSetDBItem都具有该属性。

@objc(DBCategory)
class DBCategory: NSManagedObject {

    @NSManaged var identifier: String
    @NSManaged var items: Set<DBItem>
    @NSManaged var sets: Set<DBSet>

}

And this is how I use it 这就是我的使用方式

private var elements = [AnyObject]()

private func prepareElements() {
    elements.removeAll(keepCapacity: false)
    if let items = currentCategory?.items {
        for item in items {
            elements.append(item)
        }
    }

    if let sets = currentCategory?.sets {
        for set in sets {
            elements.append(set)
        }
    }

    elements.sort {
        var previousPosition = 0
        var currentPosition = 0
        if let set = $0 as? DBSet {
            previousPosition = Int(set.position)
        }

        if let item = $0 as? DBItem {
            previousPosition = Int(item.position)
        }

        if let set = $1 as? DBSet {
            currentPosition = Int(set.position)
        }

        if let item = $1 as? DBItem {
            currentPosition = Int(item.position)
        }

        return previousPosition < currentPosition
    }
}

position is type of Int16 positionInt16类型

How can I simplify that? 我该如何简化?

Create a protocol that defines your position property. 创建定义您的position属性的协议。 Let's call it HasPosition. 我们称之为HasPosition。 Declare an array of [HasPosition]. 声明[HasPosition]的数组。 You can then sort the array directly with any of the standard sorting functions. 然后,您可以使用任何标准排序功能直接对数组进行排序。

If .position returns the same type in both cases, and that type is comparable, you can simplify that to the following: 如果两种情况下.position返回相同的类型, 并且该类型是可比较的,则可以将其简化为以下形式:

elements.sort {
    let l = ($0 as? DBSet)?.position ?? ($0 as? DBItem)?.position
    let r = ($1 as? DBSet)?.position ?? ($1 as? DBItem)?.position
    return l < r
}

The key to this working is that there is a version of < that works for optionals, where nil is defined as less than any non-nil value. 这项工作的关键是存在<的版本,该版本适用于可选项目,其中nil定义为小于任何非nil值。 So values in the array not of one of the two types will be sorted to the beginning. 因此,数组中不是两种类型之一的值将被排序到开头。

When you have the array as [AnyObject] and the position is Int16 , this should works: 当数组为[AnyObject]positionInt16 ,这应该可以工作:

elements.sort {
    ($0.position as Int16?) < ($1.position as Int16?)
}

This works because AnyObject has any @objc properties as Optional . 这是AnyObject因为AnyObject具有任何@objc属性作为Optional

Demo: 演示:

class DBItem:NSObject {
    var position:Int16
    init(position: Int16) { self.position = position }
    override var description:String  { return "DBItem(\(position))" }
}

class DBSet:NSObject {
    var position:Int16
    init(position: Int16) { self.position = position }
    override var description:String  { return "DBSet(\(position))" }
}

var elements:[AnyObject] = [
    DBItem(position: 5),
    DBSet(position: 2),
    DBItem(position: 42),
    DBSet(position: 62),
    DBSet(position: 21),
    DBItem(position: 6),
    DBSet(position: 36),
    DBItem(position: 24),
]


elements.sort {
    ($0.position as Int16?) < ($1.position as Int16?)
}

println(elements)
// -> [DBSet(2), DBItem(5), DBItem(6), DBSet(21), DBItem(24), DBSet(36), DBItem(42), DBSet(62)]

And your prepareElements() can be simplified as: 而且您的prepareElements()可以简化为:

private func prepareElements() {
    elements = []
    if let ct = currentCategory {
        elements += Array(ct.items) as [AnyObject]
        elements += Array(ct.sets) as [AnyObject]
        elements.sort {
            ($0.position as Int16?) < ($1.position as Int16?)
        }
    }
}

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

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