I have one array in Swift containing some ids of objects, and I have another array containing these objects with their ids, so something like this:
class MyObject {
let id: String
...
}
let ids: [String] = ...
let objects: [MyObject] = ...
Now the array of ids is sorted in some custom order, and I need the array of objects to be sorted in the same order. So for example:
let ids: [String] = ["1", "2", "3"]
let objects: [MyObject] = [obj3, obj1, obj2]
// obj1.id = "1"
// obj2.id = "2"
// obj3.id = "3"
objects.reorder(template: ids)
// Now objects = [obj1, obj2, obj3]
So I basically need to implement this reorder method. Does anyone have a smart suggestion how to do this in Swift? I'm using Swift 3, so all the new APIs are available to me.
You can sort
objects
in order to follow the order inids
writingAnother example
A possible solution:
Explanation:
(object, index)
tuples.Possible advantages:
Be aware that the reorder method fails if the id could not be found in
unsorted
I am not a computer science person, but it seems to me that this business of repeatedly calling
indexOf
is wasteful. Surely the right approach would be to walk through the template array (ids
in this case) once in advance, building a dictionary that associates each element with its position in the array:Now we've got a dictionary, and lookup in a dictionary is fast. So we can use each object's
id
as the key and sort on the corresponding value. Let's say that this is our initial array of objects:Now sorting is a one-liner:
The advantage here is especially obvious if you know you're going to be using
ids
as a template often, because you only have to form the dictionaryd
once and now you're ready to sort against that template as many times as you like. In effect, the dictionary memoizes the sort order. (Granted, I have not taken into account what happens if the dictionary lookup were to fail; we just crash.)We can generalize that approach, based on the fact that in order to serve as a dictionary key, the values in the template array must be hashable:
Now each template is transformed into a Cosorter instance initialized with the template array, thus causing the dictionary to be prepared, once:
Any time we want to cosort on that template, we just use that template's
lt
as the ordering function: