【问题标题】:Swift 3: Sort (formerly sort-in-place) array by sort descriptorsSwift 3:按排序描述符对数组进行排序(以前就地排序)
【发布时间】:2016-06-16 11:15:11
【问题描述】:

直到现在(Swift 2.2)我一直在愉快地使用来自this answer 的代码——它很迅速,很优雅,它像梦一样工作。

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
        }
    }
}

Swift 3 改变了一切。

使用代码迁移工具和Proposal SE- 0006 - sort() => sorted(), sortInPlace() => sort() - 我已经做到了

extension MutableCollection where Index : Strideable, Iterator.Element : AnyObject {
    /// Sort `self` in-place using criteria stored in a NSSortDescriptors array
    public mutating func sort(sortDescriptors theSortDescs: [SortDescriptor]) {
        sort {
            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: [SortDescriptor]) -> [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
        }
    }
}

'sorted' 函数可以毫无问题地编译 [并且工作]。对于“排序”,我在“排序”行出现错误:“无法将类型'(_,_)-> _'的值转换为预期的参数类型'[SortDescriptor]'”,这让我完全困惑:我不明白编译器试图在哪里转换任何东西,因为我传入了一个 SortDescriptors 数组,它应该是一个 SortDescriptor 数组。

通常,这种类型的错误意味着您正在处理应该具有确定值的选项,但由于这是一个函数参数 - 并且在 func sorted 中似乎可以顺利工作 - 我可以从中读取是'有什么不对'。到目前为止,我不知道那是什么东西,而且由于我们处于 beta 的早期阶段,所以根本没有文档。

作为一种解决方法,我从我的代码中删除了排序(以前是就地排序)函数,并将其替换为

让 sortedArray = oldArray(sorted[...] oldArray = sortedArray

但如果我能恢复我的就地排序功能,我将不胜感激。

【问题讨论】:

  • 为什么不只是像(array as NSArray).sortedArray(using: sortDescriptors) 这样的东西?桥接到提供您需要的功能的 Foundation 类型没有任何问题。
  • a) 我更喜欢避免桥接,特别是因为免费桥接可能会在某个时候消失。 (我们已经看到了这种趋势)。另外,b)我有一个可行的方法,所以这并不紧急;但我想了解这里发生了什么——我遗漏了一些东西,而且我自己看不到。
  • 你能举例说明你是如何在 Swift 2.2 中使用这些方法的吗?

标签: nstableview nssortdescriptor swift3


【解决方案1】:

比较 Swift 2.2 中可用的方法:

使用 Swift 3 中的方法:

请注意,Swift 3 没有接受 isOrderedBefore 闭包的 sort 方法。

这就是你的函数无法编译的原因。

这看起来像一个错误,因此我在 bugreport.apple.com 上将其报告为错误 26857748。

【讨论】:

  • 你从哪里找到这些方法的?在 Xcode 8 中,我只在代码完成中获得 isOrderedBefore 变体。 (在 Playground 中排序和排序,iOS 和 MacOS;仅在 MacOS 项目中排序)。 sorted(sortDescriptors:) 变体可用于 MacOS 项目中的 NSArray,但不适用于 Playground 文件。
  • 以上来自 Xcode 8 中的 iOS Playground 文件。
  • Apple 说该方法现在是 sort(by:),但我在 MutableCollection 上找不到此方法。它似乎只存在于 EmptyCollection 和 CollectionOfOne.
  • 尝试对 MutableCollection 调用 sort 会导致错误:“sort”已重命名为“sorted(by:)”。但是这个方法返回一个新数组,它没有就地排序。
【解决方案2】:

让 sortedArray = users.sorted { $0.name

【讨论】:

  • OP 想要就地排序,而不是创建一个新数组。
【解决方案3】:

使用RandomAccessCollection协议

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
        }
    }
}

【讨论】:

    【解决方案4】:

    Swift 3.0

    let sortedCapitalArray = yourArray.sorted {($0 as AnyObject).localizedCaseInsensitiveCompare(($1 as AnyObject)as! String) == ComparisonResult.orderedAscending}
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-01-12
      • 2011-07-06
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多