我想基于定义元素顺序的自定义数组对数组的元素进行排序.例如,假定以下数组:
I would like to sort the elements of an array based on a custom array that defines the element order. For example, assume the following array:
let arr = ["second", "first", "second", "fourth", "third", "second"]我试图创建一个数组扩展名,以便能够通过以下方式对该数组进行排序:
I tried to create an Array extension to be able to sort this array by:
let sortedArr = arr.sortBy(orderArray: ["first","second","third","fourth"]) // desired output: ["first", "second", "second", "second", "third", "fourth":但是,该扩展名无法正常工作:
However, the extension does not work correctly:
extension Array { public func sortBy<T: Comparable>(orderArray: [T]) -> [T]? { guard self.count > 0, self.first! as? T != nil else { return nil } let indices = self.map {orderArray.index(of: $0 as! T)! } return self.sorted { indices[$0] > indices[$1] } // This doesn’t work } }有什么想法吗?
推荐答案您的代码的一个问题是self.sorted期望 封闭比较数组 elements 而不是索引.
One problem with your code is that self.sorted expects a closure comparing array elements, not indices.
这是一个可能的解决方案,也避免了不必要的操作 键入强制转换和展开(内嵌解释):
Here is a possible solution which also avoids unnecessary type casts and unwrappings (explanations inline):
extension Array where Element: Equatable { public func sortBy(orderArray: [Element]) -> [Element]? { // Index of each element in `orderArray`: let targetIndices = self.flatMap { orderArray.index(of: $0) } // Verify that each array element occurs in `orderArray`: guard targetIndices.count == self.count else { return nil } // Sort array indices according to their index in `orderArray`: let sortedIndices = self.indices.sorted { targetIndices[$0] < targetIndices[$1] } // Rearrange elements accordingly: return sortedIndices.map { self[$0] } } }示例:
let arr = ["second", "first", "second", "fourth", "third", "second"] if let sortedArr = arr.sortBy(orderArray: ["first","second","third","fourth"]) { print(sortedArr) // ["first", "second", "second", "second", "third", "fourth"] }
移动orderArray中不包含的数组元素 到排序结果的末尾(但保留它们的相对顺序),将代码略微修改为
To move array elements which are not contained in orderArray to the end of the sorted result (but preserve their relative order), modify the code slightly to
extension Array where Element: Equatable { public func sortBy(orderArray: [Element]) -> [Element] { // Index of each element in `orderArray`: let targetIndices = self.enumerated().map { orderArray.index(of: $1) ?? orderArray.count + $0 } // Sort array indices according to their index in `orderArray`: let sortedIndices = self.indices.sorted { targetIndices[$0] < targetIndices[$1] } // Rearrange elements accordingly: return sortedIndices.map { self[$0] } } }示例:
let arr = ["x", "second", "first", "y", "second", "fourth", "third", "second", "z"] let sortedArr = arr.sortBy(orderArray: ["first","second","third","fourth"]) print(sortedArr) // ["first", "second", "second", "second", "third", "fourth", "x", "y", "z"]更多推荐
如何根据预定义的元素顺序对数组排序?
发布评论