Sort one String array to match another

时间:2016-10-20 13:22:00

标签: swift

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

5 个答案:

答案 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)!
})