Swift standard library already offers a useful set of sort() functions. However, it is also often useful to know how the collection should be rearranged in order to become sorted. For example, R defines the order() function which returns a permutation of collection indexes which rearrange the collection in an order. I suggest to add similar functionality to the Swift Collections E.g.:
var out =
for i in collection.order({$0 < $1}) { out.append(collection[i]) }
// out is now sorted collection
Knowing the sort order is useful in many applications where the data cannot or should not be rearranged and yet some information about the ordering is helpful, e.g. for traversing the collection in a specific way. It is also helpful for maintaining multiple ordering relations associated with the same collection.
The implementation should be fairly straightforward. E.g. here is an extension method I use:
This way you can `order` all sequences, and it is more efficient as you don’t fetch elements by index inside the `isOrderedBefore`. (You could also *not* `map` at the end and return all the elements along with their original indexes.)
milos
···
On 11 Apr 2016, at 08:48, Taras Zakharko via swift-evolution <swift-evolution@swift.org> wrote:
I think it depends on how expensive the indexed access is on the collection. I use it primarily on arrays, where self[i] essentially boils down to a pointer dereference, so I expect the generated code to be very efficient. Your version might be faster for collection with expensive element access, but it should be slower for arrays and the like, as it involves additional intermediate structure allocations and copies.
This way you can `order` all sequences, and it is more efficient as you don’t fetch elements by index inside the `isOrderedBefore`. (You could also *not* `map` at the end and return all the elements along with their original indexes.)
extension CollectionType {
func order(@noescape isOrderedBefore areInOrder: (Generator.Element, Generator.Element) -> Bool) -> [Index] {
var a = Array(indices)
a.sortInPlace { areInOrder(self[$0], self[$1]) }
return a
}
}
···
on Mon Apr 11 2016, Taras Zakharko <swift-evolution@swift.org> wrote:
Hi,
I think it depends on how expensive the indexed access is on the collection. I
use it primarily on arrays, where self[i] essentially boils down to a pointer
dereference, so I expect the generated code to be very efficient. Your version
might be faster for collection with expensive element access, but it should be
slower for arrays and the like, as it involves additional intermediate structure
allocations and copies.
This way you can `order` all sequences, and it is more efficient as you
don’t fetch elements by index inside the `isOrderedBefore`. (You could also
*not* `map` at the end and return all the elements along with their original
indexes.)
On 11 Apr 2016, at 19:38, Taras Zakharko <taras.zakharko@uzh.ch <mailto:taras.zakharko@uzh.ch>> wrote:
Your version might be faster for collection with expensive element access, but it should be slower for arrays and the like, as it involves additional intermediate structure allocations and copies.
No, not really. The cost of my enumeration and mapping is linear so they add nothing to the sorting order of complexity. Your two subscript calls inside the predicate, however, definitely do. In other words, your implementation will not be faster under any circumstances and it will in fact grow nonlinearly slower compared to the enumeration approach as the length of array increases…
milos
(My message appear to have bounced: I’m sorry if I end up sending multiple copies!)