我有一个Item
数组。该顺序永远不会得到保证,因为集合是从基于其他地方的许多用户操作的API提供的。
但是,我需要按type
字段对这个集合进行排序,这样我就可以在其他地方正确地迭代它。
在下面的示例游乐场的情况下,我需要一个遵循以下逻辑的重新排序的集合:
[
Item(type: .foo),
Item(type: .bar),
Item(type: .boo),
Item(type: .baz),
Item(type: .boom),
Item(type: .bang)
]
具体来说,.foo
和.bar
应该是前两项,.boom
和bang
将是最后两项。
这些固定项是唯一的,响应中不会存在重复项。
剩下的所有东西都应该在这两个组之间,顺序与原始集合中的顺序相同。
我已经尝试在var output: [Item]
中将项目拆分为两个集合,并在索引处插入第二个集合,但是排序仍然是错误的。
我如何才能做到这一点?
import UIKit
enum ItemType: String {
case foo
case bar
case boo
case baz
case boom
case bang
}
struct Item {
let type: ItemType
}
let props = [
Item(type: .bang),
Item(type: .bar),
Item(type: .baz),
Item(type: .boo),
Item(type: .boom),
Item(type: .foo)
]
/*
case foo
case bar
> ----------- should be ordered in same order as in `props`
case boom
case bang
*/
var output: [Item] {
var fixedPosition: [Item] = []
var dynamicPosition: [Item] = []
props.forEach { item in
if (item.type == .foo || item.type == .bar || item.type == .boom || item.type == .bang ){
fixedPosition.append(item)
} else {
dynamicPosition.append(item)
}
}
var result: [Item] = fixedPosition
result.insert(contentsOf: dynamicPosition, at: 1)
return result
}
print(output.map { $0.type })
发布于 2020-06-01 09:34:09
您可以为每个枚举案例提供一个int值,并对其进行稳定排序:
func intValue(for itemType: ItemType) -> Int {
switch itemType {
case .foo:
return 0
case .bar:
return 1
case .boo, .baz: // the order of these should remain the same, so they get the same number
return 2
case .boom:
return 3
case .bang:
return 4
}
}
let sorted = props.stableSorted(by: { intValue(for: $0.type) < intValue(for: $1.type) })
stableSort
取自this answer by leavez
extension RandomAccessCollection {
/// return a sorted collection
/// this use a stable sort algorithm
///
/// - Parameter areInIncreasingOrder: return nil when two element are equal
/// - Returns: the sorted collection
public func stableSorted(by areInIncreasingOrder: (Element, Element) throws -> Bool) rethrows -> [Element] {
let sorted = try enumerated().sorted { (one, another) -> Bool in
if try areInIncreasingOrder(one.element, another.element) {
return true
} else {
return one.offset < another.offset
}
}
return sorted.map { $0.element }
}
}
发布于 2020-06-01 11:34:04
实施Comparable
协议的ItemType
变体:
extension ItemType: Comparable {
static func < (lhs: ItemType, rhs: ItemType) -> Bool {
// function returns `true` iff lhs is smaller than res
// order of cases matters here, switch matches them left-to-right, top-to-bottom
switch (lhs, rhs) {
case (.foo, _): // .foo is before everyone else
return true
case (_, .foo): // nothing is "smaller" than .foo
return false
case (.bar, _): // .bar can be preceded only by .foo (previous 2 cases handle it)
return true
case (_, .bang): // .bang is always last
return true
case (.bang, _): // nothing is "bigger" than .bang
return false
case (_, .boom): // .boom can be only before .bang (previous 2 cases handle it)
return true
default: // otherwise we don't care about comparing items, neither item is "smaller" than other
return false
}
}
}
https://stackoverflow.com/questions/62129078
复制