按其他数组中的值顺序对数组进行排序

时间:2017-05-17 06:25:13

标签: arrays swift sorting

我有一个定义订单的数组

let orderSettingArray = ["Admiral", "Captain", "Lieutenant"]

和另一个包含其中一些值的数组

var myArray = ["Lieutenant", "Captain"]

我想对myArray进行排序以反映orderSettingArray的顺序:

var myArraySorted = myArray.getSorted(by: orderSettingArray)

现在print(myArraySorted)应该打印["Captain", "Lieutenant"]

4 个答案:

答案 0 :(得分:6)

如此简单Printer.prototype = { /** * Representation print table */ printTable: function (table) { var str = ''; for (var i = 0; i < table.width; i++) { var x = i; for (var j = 0; j < table.height; j++) { var y = j; str += '' + table.getValueAt(x, y) + '|'; } str += '\n------------\n'; } console.log(str); }, /** * Representation check winner conditional */ printWinner: function (player) { }, }; Math.floor(Math.random() * 2); /** * @param newTable [array] : The array two-direction table * @param player [object] : the object contain player X and O */ var GamePlay = function (table, playerOne, playerTwo) { this.table = table; this.playerOne = playerOne; this.playerTwo = playerTwo; this.printer = new Printer(); }; GamePlay.prototype = { run: function (x, y) { console.log('Game start ...!'); x = Math.floor(Math.random() * 2); y = Math.floor(Math.random() * 2); this.putChessman(x, y, this.playerOne.ch); console.log('put', this.putChessman()); this.printer.printTable(this.table); }, /** * @param player [keywork] : the keywork X and O */ checkWin: function (player) { }, putChessman: function (x, y, ch) { console.log('isEmptyAt', table.isEmptyAt(x, y)); if (this.table.isEmptyAt(x, y) === true) { console.log('@ player ' + ch + ' put'); this.table.setPosition(x, y, ch); } else { console.log('@ Other player already put on it'); } }, }; var table = new Table(3, 3); var playerOne = new Player('playerOne', 'O'); var playerTwo = new Player('playerTwo', 'X'); var game = new GamePlay(table, playerOne, playerTwo); game.run();

答案 1 :(得分:2)

  • 将每个数组元素映射到(element, index)元组,其中 index是order数组中数组元素的索引。 在您的示例中

    [("Lieutenant", 2), ("Captain", 1)]
    
  • 按第二个元组元素(索引)对元组数组进行排序。 在你的情况下

    [("Captain", 1), ("Lieutenant", 2)]
    
  • 从已排序的元组数组中提取数组元素。 在你的情况下

    ["Captain", "Lieutenant"]
    

代码(对于任何可等元素数组,不限于字符串数组):

extension Array where Element: Equatable {
    func getSorted(by orderArray: [Element]) -> [Element] {

        return self.map { ($0, orderArray.index(of: $0) ?? Int.max) }
            .sorted(by: { $0.1 < $1.1 })
            .map { $0.0 }

    }
}

let orderSettingArray = ["Admiral", "Captain", "Lieutenant"]
let myArray = ["Lieutenant", "Captain"]
let myArraySorted = myArray.getSorted(by: orderSettingArray)
print(myArraySorted) // ["Captain", "Lieutenant"]

myArray中不存在的orderSettingArray中的元素 被赋予索引Int.max,因此排序到最后 结果。

答案 2 :(得分:1)

Swift 3

extension Array where Element: Hashable {
    func getSorted(by: Array<String>) -> Array<String> {
        var d = Dictionary<Int, String>()

        for value in self {
            for i in 0 ..< by.count {
                if value as! String == by[i] {
                    d[i] = value as? String
                }
            }
        }

        var sortedValues = Array<String>()
        for key in d.keys.sorted(by: <) {
            sortedValues.append(d[key]!)
        }

        return sortedValues
    }
}

答案 3 :(得分:1)

我为此写了一个扩展名。它非常灵活,因为它允许您定义输入排序的字段,以及如何处理排序顺序未根据sortingOrder列表定义的元素。

它很长,所以我建议你把它藏在自己的文件中:

enum UnspecifiedItemSortingPolicy {
    case first
    case last
    case omitEntirely
    case assertAllItemsHaveDefinedSorting
}

extension MutableCollection {
    typealias Element = Iterator.Element

    func sorted<T: Equatable>(
            byOrderOf sortingMemberDeriver: @escaping (Element) -> T,
            in sortingOrder: [T],
            sortUnspecifiedItems unspecifiedItemSortingPolicy: UnspecifiedItemSortingPolicy = .assertAllItemsHaveDefinedSorting
        ) -> [Element] {

        switch unspecifiedItemSortingPolicy {
            case .omitEntirely: return self
                    .lazy
                    .map { (element: Element) -> (element: Element, position: Int) in
                        let sortingMember = sortingMemberDeriver(element)
                        guard let position = sortingOrder.index(of: sortingMember) else {
                            fatalError("Attempted to sort a collection (\(self)) containing an item (\(element)) whose ordering was not defined in the sorting order: \(sortingOrder).")
                        }
                        return (element: element, position: position)
                    }
                    .sorted{ $0.position < $1.position }
                    .map{ $0.element }



            case .assertAllItemsHaveDefinedSorting: return self
                    .lazy
                    .flatMap { (element: Element) -> (element: Element, position: Int)? in
                        let sortingMember = sortingMemberDeriver(element)
                        return sortingOrder.index(of: sortingMember).map{ (element: element, position: $0) }
                    }
                    .sorted{ $0.position < $1.position }
                    .map{ $0.element }



            case .first, .last:
                var unspecifiedItems = Array<Element>() //items whose ordering isn't in the sortingOrder

                let sortedPortion = self.flatMap { (element: Element) -> (element: Element, position: Int)? in
                        let sortingMember = sortingMemberDeriver(element)
                        guard let position = sortingOrder.index(of: sortingMember) else {
                            unspecifiedItems.append(element)
                            return nil
                        }
                        return (element: element, position: position)
                    }
                    .sorted{ $0.position < $1.position }
                    .map{ $0.element }

                switch unspecifiedItemSortingPolicy {
                    case .first: return unspecifiedItems + sortedPortion
                    case .last: return sortedPortion + unspecifiedItems
                    default: fatalError("This should never happen.")
                }
        }
    }
}

extension MutableCollection where Iterator.Element: Equatable {
    func sorted(
            byOrderIn sortingOrder: [Element],
            sortUnspecifiedItems unspecifiedItemSortingPolicy: UnspecifiedItemSortingPolicy = .assertAllItemsHaveDefinedSorting
        ) -> [Element] {
        return self.sorted(byOrderOf: {$0}, in: sortingOrder, sortUnspecifiedItems: unspecifiedItemSortingPolicy)
    }
}

从那里开始,使用起来非常简单和优雅:

let sortingOrder = ["Admiral", "Captain", "Lieutenant"]

let ranks = ["Lieutenant", "Captain"]
let sortedRanks = ranks.sorted(byOrderIn: sortingOrder)

print(sortedRanks)

与大多数其他解决方案不同,您会看到此问题,此扩展程序会处理您排序的数组包含排序顺序未在sortingOrder数组中定义的项目的情况。有一个默认参数,允许您指定这些项目是首先(.first),最后一个(.last),还是从结果中完全省略(.omitEntirely)。 / p>

此外,该算法仅对正在排序的数组的每个元素执行一次index(of:)调用,因此即使在对大型数组进行排序时,性能也相当不错。但是,此算法为O(sortingOrder.count)。如果sortingOrder中有很多元素,那么可能需要重构这个来获取字典,将元素映射到定义排序顺序的亲属整数。