根据不同 NSOrderedSet 中指定的顺序重新排序 NSOrderedSet

Reorder NSOrdered Set based on the order specified in a different NSOrderedSet

所以,我有两个有序集,它们的结构是这样的,一个有序集基本上有一个字典列表,另一个有序集有与字典中某个值对应的字符串。让我用一个例子来说明:

OrderedSetA = [["key1": "test", "key2": "A"], ["key1": "test2", "key2": "B"], ["key1": "test3", "key2":"C"], ["key1": "test4", "key2": "E"]]
OrderedSetB = ["B","G","H", "A", "E", "D", "C", "F", "J", "K"]

所以,现在我基本上想根据为与 OrderedSet B 中的 key2 对应的字符串指定的顺序重新排列 OrderedSetA 中的元素,同时忽略 B 中不在 A 中的任何值。所以例如,在这种情况下,我要寻找的是:

OrderedSetC = [["key1": "test2", "key2": "B"], ["key1": "test1", "key2": "A"], ["key1": "test4", "key2":"E"], ["key1": "test3", "key2": "C"]]

这是我到目前为止尝试过的方法:

let orderedSetC = orderedSetA.filter {OrderedSetB.contains(([=14=] as AnyObject).key2)}

这里发生的是 returns 同样的事情,我想我是根据 OrderedSetB 中的任何东西进行过滤,它不在 OrderedSetA 中,但是没有 sorting/reordering 发生.

什么是最合适和最有效的 Swift 5 处理方法?

谢谢!

您可以使用带谓词的过滤器:

let osA: NSOrderedSet = ["A", "B", "C", "D", "E", "F"]
let osB: NSOrderedSet = ["B", "G", "H", "A", "C", "D", "E", "F", "J", "K"]

let osC = osB.filtered(using: .init(block: { (element, _) in
    osA.contains(element as Any)
}))

您还可以创建一个有序集 B 的 NSMutableOrderedSet 并与 A 相交:

var osC = osB.mutableCopy() as! NSMutableOrderedSet
osC.intersect(osA)
print(Array(osC))   // ["B", "A", "C", "D", "E", "F"]

另一种选择是实施您自己的本机 Swift OrderedSet,正如我在此 answer 中发布的那样。将 OrderedSet 添加到您的项目后,您可以简单地获得有序集 A intersection ordered set B:

let osA: OrderedSet = ["A", "B", "C", "D", "E", "F"]
let osB: OrderedSet = ["B", "G", "H", "A", "C", "D", "E", "F", "J", "K"]

let osC = osB.intersection(osA)  // ["B", "A", "C", "D", "E", "F"] 


edit/update:

不确定为什么需要 NSOrderedSet 词典。 IMO 你应该构建你的数据。无论如何,如果你真的想这样做,你可以使用 reduce(into:):

let osA: NSOrderedSet = [["key1": "test", "key2": "A"], ["key1": "test2", "key2": "B"], ["key1": "test3", "key2":"C"], ["key1": "test4", "key2": "E"]]
let osB: NSOrderedSet = ["B","G","H", "A", "E", "D", "C", "F", "J", "K"]

let osC: NSMutableOrderedSet = osB.reduce(into: .init(), { (os, any) in
    guard let object = osA.first(where: { element in
        (element as? [String: String] ?? [:])?.values.contains(any as? String ?? "") == true
    }) else { return }
    os.add(object)
})