如何根据预定义的元素顺序对数组排序? [英] How to sort an array based on a predefined element order?

查看:116
本文介绍了如何根据预定义的元素顺序对数组排序?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想基于定义元素顺序的自定义数组对数组的元素进行排序.例如,假定以下数组:

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"]

这篇关于如何根据预定义的元素顺序对数组排序?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆