Swift:按排序描述符排序数组

时间:2021-10-31 15:59:31

I am using coredata so I need sort descriptors for my entities

我正在使用coredata,所以我需要为我的实体排序描述符

For example, a Coordinate-entity has this class func:

例如,一个协调实体拥有这个类func:

class func sortDescriptors() -> Array<NSSortDescriptor>
{
    return [NSSortDescriptor(key: "sequence", ascending: true)]
}

I am using this when doing fetch-requests to CoreData like this:

当我对CoreData进行这样的获取请求时,我使用了这个:

var request = NSFetchRequest(entityName: entityName)

request.sortDescriptors = T.sortDescriptors()

However, when I have an array of coordinates as a property on another coredata object, this is an NSSet (I.e. unsorted)

然而,当我在另一个coredata对象上有一个作为属性的坐标数组时,这是一个NSSet(即未排序的)

To solve this, I am returning the coordinates like this:

为了解决这个问题,我将返回这样的坐标:

return NSArray(array: coordinates!).sortedArrayUsingDescriptors(Coordinate.sortDescriptors()) as? Array<Coordinate>

Which feels ugly, to use an NSArray just to get the sortedArrayUsingDescriptors-method. Is there a similar way to do this directly on a Swift-array, I.e. Array<Coordinate> by using sort descriptors?

用NSArray来获取sortedarrayusingdescriptors方法,感觉很难看。是否有一种类似的方法可以直接在一个Swift-array(即数组 通过使用排序描述符)上执行此操作?

Thank you!

谢谢你!

3 个解决方案

#1


10  

There is no built-in method for this, but you can add them using protocol extension:

对此没有内置的方法,但是可以使用协议扩展名添加:

extension MutableCollectionType where Index : RandomAccessIndexType, Generator.Element : AnyObject {
    /// Sort `self` in-place using criteria stored in a NSSortDescriptors array
    public mutating func sortInPlace(sortDescriptors theSortDescs: [NSSortDescriptor]) {
        sortInPlace {
            for sortDesc in theSortDescs {
                switch sortDesc.compareObject($0, toObject: $1) {
                case .OrderedAscending: return true
                case .OrderedDescending: return false
                case .OrderedSame: continue
                }
            }
            return false
        }
    }
}

extension SequenceType where Generator.Element : AnyObject {
    /// Return an `Array` containing the sorted elements of `source`
    /// using criteria stored in a NSSortDescriptors array.
    @warn_unused_result
    public func sort(sortDescriptors theSortDescs: [NSSortDescriptor]) -> [Self.Generator.Element] {
        return sort {
            for sortDesc in theSortDescs {
                switch sortDesc.compareObject($0, toObject: $1) {
                case .OrderedAscending: return true
                case .OrderedDescending: return false
                case .OrderedSame: continue
                }
            }
            return false
        }
    }
}

But note that this will work only when the array elements are classes, not structures, as NSSortDescriptor compareObject method requires arguments conforming to AnyObject

但是请注意,这只在数组元素是类而不是结构时才会起作用,因为NSSortDescriptor compareObject方法需要符合AnyObject的参数

#2


8  

Another approach to the nice extensions of Damien could be a multi-cast.

达米安的另一种不错的扩展方式是多播。

myArray = (myArray as NSArray).sortedArrayUsingDescriptors(tableView.sortDescriptors) as! Array

Original source: NSHipster

原始资料来源:NSHipster

#3


4  

Swift 3 Version of @Darniel's answer

Swift 3版本的@Darniel的回答

extension MutableCollection where Self : RandomAccessCollection {
    /// Sort `self` in-place using criteria stored in a NSSortDescriptors array
    public mutating func sort(sortDescriptors theSortDescs: [NSSortDescriptor]) {
        sort { by:
            for sortDesc in theSortDescs {
                switch sortDesc.compare($0, to: $1) {
                case .orderedAscending: return true
                case .orderedDescending: return false
                case .orderedSame: continue
                }
            }
            return false
        }

    }
}

extension Sequence where Iterator.Element : AnyObject {
    /// Return an `Array` containing the sorted elements of `source`
    /// using criteria stored in a NSSortDescriptors array.

    public func sorted(sortDescriptors theSortDescs: [NSSortDescriptor]) -> [Self.Iterator.Element] {
        return sorted {
            for sortDesc in theSortDescs {
                switch sortDesc.compare($0, to: $1) {
                case .orderedAscending: return true
                case .orderedDescending: return false
                case .orderedSame: continue
                }
            }
            return false
        }
    }
}

#1


10  

There is no built-in method for this, but you can add them using protocol extension:

对此没有内置的方法,但是可以使用协议扩展名添加:

extension MutableCollectionType where Index : RandomAccessIndexType, Generator.Element : AnyObject {
    /// Sort `self` in-place using criteria stored in a NSSortDescriptors array
    public mutating func sortInPlace(sortDescriptors theSortDescs: [NSSortDescriptor]) {
        sortInPlace {
            for sortDesc in theSortDescs {
                switch sortDesc.compareObject($0, toObject: $1) {
                case .OrderedAscending: return true
                case .OrderedDescending: return false
                case .OrderedSame: continue
                }
            }
            return false
        }
    }
}

extension SequenceType where Generator.Element : AnyObject {
    /// Return an `Array` containing the sorted elements of `source`
    /// using criteria stored in a NSSortDescriptors array.
    @warn_unused_result
    public func sort(sortDescriptors theSortDescs: [NSSortDescriptor]) -> [Self.Generator.Element] {
        return sort {
            for sortDesc in theSortDescs {
                switch sortDesc.compareObject($0, toObject: $1) {
                case .OrderedAscending: return true
                case .OrderedDescending: return false
                case .OrderedSame: continue
                }
            }
            return false
        }
    }
}

But note that this will work only when the array elements are classes, not structures, as NSSortDescriptor compareObject method requires arguments conforming to AnyObject

但是请注意,这只在数组元素是类而不是结构时才会起作用,因为NSSortDescriptor compareObject方法需要符合AnyObject的参数

#2


8  

Another approach to the nice extensions of Damien could be a multi-cast.

达米安的另一种不错的扩展方式是多播。

myArray = (myArray as NSArray).sortedArrayUsingDescriptors(tableView.sortDescriptors) as! Array

Original source: NSHipster

原始资料来源:NSHipster

#3


4  

Swift 3 Version of @Darniel's answer

Swift 3版本的@Darniel的回答

extension MutableCollection where Self : RandomAccessCollection {
    /// Sort `self` in-place using criteria stored in a NSSortDescriptors array
    public mutating func sort(sortDescriptors theSortDescs: [NSSortDescriptor]) {
        sort { by:
            for sortDesc in theSortDescs {
                switch sortDesc.compare($0, to: $1) {
                case .orderedAscending: return true
                case .orderedDescending: return false
                case .orderedSame: continue
                }
            }
            return false
        }

    }
}

extension Sequence where Iterator.Element : AnyObject {
    /// Return an `Array` containing the sorted elements of `source`
    /// using criteria stored in a NSSortDescriptors array.

    public func sorted(sortDescriptors theSortDescs: [NSSortDescriptor]) -> [Self.Iterator.Element] {
        return sorted {
            for sortDesc in theSortDescs {
                switch sortDesc.compare($0, to: $1) {
                case .orderedAscending: return true
                case .orderedDescending: return false
                case .orderedSame: continue
                }
            }
            return false
        }
    }
}