I have one array that defines an order,
let orderSettingArray = ["Admiral", "Captain", "Lieutenant"]
and another array with a few of these values
var myArray = ["Lieutenant", "Captain"]
I want to sort myArray
to reflect the order of orderSettingArray
:
var myArraySorted = myArray.getSorted(by: orderSettingArray)
Now print(myArraySorted)
should print ["Captain", "Lieutenant"]
Update
I've found a better design for this. It has quite a few improvements:
Dictionary
to speed up ordering look-upsomitEntirely
responsibility was removed entirely. It should instead by done by a simple call tofilter
, withhardcodedOrdering.contains
as the predicate.See my new answer, here
Old answer:
I have written an extension just for this. It's pretty flexible, in that it lets you define by what field the input is sorted, and how to handle elements whose sort ordering isn't defined according to the sortingOrder list.
It's pretty long, so I suggest you tuck it away in its own file:
From there, the usage is really easy and elegant:
Unlike most other solutions you'll see to this problem, this extension handles the cases where the array you're sorting contains items whose sort order is not defined in the
sortingOrder
array. There's a defaulted argument that lets you specify whether such items should come first (.first
), last (.last
), or be omitted entirely (.omitEntirely
) from the result.Additionally, this algorithm only performs one
index(of:)
call per element of the array being sorted, so performance is pretty decent even when sorting large arrays. However, this algorithm isO(sortingOrder.count)
. If there are a lot of elements insortingOrder
, then it might be worth refactoring this to take a dictionary, mapping elements to relatives integers that define the sort order.So Easy
let new = orderSettingArray.filter{ return myArray.contains($0) }
Swift 3
Map each array element to a
(element, index)
tuple, where the index is the index of the array element in the order array. In your example that would beSort the array of tuples by the second tuple element (the index). In your case
Extract the array elements from the sorted tuples array. In your case
Code (for any array of equatable elements, not restricted to arrays of strings):
Elements in
myArray
which are not present inorderSettingArray
are assigned the indexInt.max
and therefore sorted to the end of the result.