简体   繁体   中英

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

So, I have two ordered sets and things are structured in a way where one ordered set basically has a list of dictionaries and the other ordered set has strings that correspond with a certain value in the dictionar. Let me illustrate, using an example:

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"]

So, now I basically want to rearrange elements in OrderedSetA based on the order specified for strings that correspond with key2 in OrderedSet B while ignoring any of the values in B that aren't in A. So for example, in this scenario, what I'd be looking for is something like:

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

Here's what I've tried so far:

let orderedSetC = orderedSetA.filter {OrderedSetB.contains(($0 as AnyObject).key2)}

And what happens here is that it just returns the same thing, I think I'm filtering based on whatever is OrderedSetB, that isn't in OrderedSetA however there is no sorting/reordering happening.

What would be the most appropriate and effective Swift 5 based way of handling this?

Thanks!

You can use filter with a predicate:

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)
}))

You can also create a NSMutableOrderedSet of your ordered set B and intersect with A:

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

Another option is to implement your own native Swift OrderedSet as I have posted in this answer . After adding the OrderedSet to your project you could simply get ordered set 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:

Not sure why would you need a NSOrderedSet of dictionaries. IMO you should structure your data. Anyway if you really want to do it this way you can use 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)
})

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM