我有一个定义订单的数组
let orderSettingArray = ["Admiral", "Captain", "Lieutenant"]
和另一个包含其中一些值的数组
var myArray = ["Lieutenant", "Captain"]
我想对myArray
进行排序以反映orderSettingArray
的顺序:
var myArraySorted = myArray.getSorted(by: orderSettingArray)
现在print(myArraySorted)
应该打印["Captain", "Lieutenant"]
答案 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)
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
中有很多元素,那么可能需要重构这个来获取字典,将元素映射到定义排序顺序的亲属整数。