What would be the cleanest way to sort one array to match another array:
Example:
public class Account {
public var identifier: String
init(id identifier:String) {
self.identifier = identifier
}
}
let knownOrder = ["abc", "klm", "def", "hij"]
var givenOrder = [Account(id: "abc"), Account(id: "def"), Account(id: "hij"), Account(id: "klm")]
what would be the easiest way to make the output for givenOrder match knownOrder without altering knownOrder?
Added a little more to the example. Im trying to get the given list of Account objects with an identifier property to be in the same order as a stored list of strings which match the users preference to have their accounts
答案 0 :(得分:3)
你需要这样的东西吗?
let knownOrder = ["a1", "b2", "c3", "d4"]
var givenOrder = ["c3", "a1", "d4", "b2"]
givenOrder.sort { (lhs, rhs) -> Bool in
(knownOrder.index(of: lhs) ?? 0) < (knownOrder.index(of: rhs) ?? 0)
}
?? 0
如果givenOrder
包含的值不在knownOrder
中,那么这些值将在列表的开头未分类。
答案 1 :(得分:1)
在Swift 5中,index(of:)
已替换为firstIndex(of:)
:
let results = givenOrder.sorted {
(knownOrder.firstIndex(of: $0. identifier) ?? 0) < (knownOrder.firstIndex(of: $1. identifier) ?? 0)
}
但是请注意,firstIndex(of:)
(以前称为index(of:)
)为O(n),并且在sorted
闭包中重复执行此操作效率不高。您可能要建立字典:
let order = Dictionary(uniqueKeysWithValues: knownOrder.enumerated().map { ($0.1, $0.0) })
然后,当您在order
字典中查找每个对象的顺序时,您现在可以享受O(1)的性能:
let results = givenOrder.sorted {
(order[$0.identifier] ?? 0) < (order[$1.identifier] ?? 0)
}
答案 2 :(得分:0)
最简单的方法是使用&#34; for&#34;。
let knownOrder = ["a1", "b2", "c3", "d4"]
var givenOrder = ["c3", "a1", "d4", "b2"]
var result = [String]()
for item in knownOrder {
if let index = givenOrder.index(of: item) {
result.append(item)
givenOrder.remove(at: index)
}
}
for item in givenOrder {
result.append(item)
}
print(result)
循环knownOrder的每一项,如果该项还包含在givenOrder中,则将其添加到result中,并将其从givenOrder中删除。
然后将givenOrder的左侧项添加到结果中。
这很容易理解,但是如果你有大数据,代码可能会很慢。
答案 3 :(得分:0)
您可以创建一个可订阅的课程来管理帐户,但我不确定字典搜索大数据的速度有多慢...
class AccountManager {
var accounts: [String: Account]
init(accounts: [Account]) {
var accountDict = [String: Account]()
for i in accounts {
accountDict[i.identifier] = i
}
self.accounts = accountDict
}
func sort(by ids: [String]) -> [Account] {
return ids.map({accounts[$0]}).flatMap({$0})
}
subscript(id: String) -> Account? {
return accounts[id]
}
}
答案 4 :(得分:0)
您可以通过以下方式完成此任务:
givenOrder = givenOrder.sort({
(knownOrder.indexOf($0.identifier) ?? 0) <
(knownOrder.indexOf($1.identifier) ?? 0)
})
如果您肯定knownOrder
将包含所有标识符(并且如果它没有关注,则不会担心潜在的崩溃),您可以将其浓缩为:< / p>
givenOrder = givenOrder.sort({
knownOrder.indexOf($0.identifier)! <
knownOrder.indexOf($1.identifier)!
})