Skip to content

Add function to sort the elements of an array.#17

Open
enzoh wants to merge 16 commits intomasterfrom
enzoh/sort
Open

Add function to sort the elements of an array.#17
enzoh wants to merge 16 commits intomasterfrom
enzoh/sort

Conversation

@enzoh
Copy link
Copy Markdown
Contributor

@enzoh enzoh commented May 7, 2020

No description provided.

@enzoh enzoh requested a review from nomeata May 7, 2020 08:44
@nomeata
Copy link
Copy Markdown
Contributor

nomeata commented May 7, 2020

Thanks! But this should better come with some test cases, right…

Comment thread src/Array.mo Outdated
Sorts the elements of an array using the given comparison function.
*/
public let sortBy : <A> ([A], (A, A) -> Int) -> [A] =
func<A>(arr : [A], compare : (A, A) -> Int) : [A] {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Base library uses { #lt; #eq; #gt; } as return type for compare function. See https://github.com/dfinity-lab/motoko-base/blob/master/src/Heap.mo#L13 as an example.

btw, you can already use HeapSort via the Heap module, but of course quick sort is faster in arrays before we start to implement pairing heap.

@nomeata nomeata requested review from matthewhammer and removed request for nomeata May 7, 2020 20:43
@enzoh enzoh requested a review from chenyan-dfinity May 8, 2020 00:54
@kritzcreek
Copy link
Copy Markdown
Contributor

kritzcreek commented May 8, 2020

Most standard libraries I know of (Java, Python, Haskell, Rust, ...) use a version of Mergesort (or Timsort) as their default sort implementations.

The main benefit there is that having a stable sort is the better default.

It's also to protect against DOS attacks as Quicksort degrades to O(n^2) if I can predict your pivot choices. Given that we don't have access to randomness that's even easier than it usually is.

I think adding a Quicksort as sortUnstable and adding a disclaimer about the potential n^2 is just fine, but I'd prefer our Array.sort to be a stable sort.

Comment thread test/arrayTest.mo
@enzoh
Copy link
Copy Markdown
Contributor Author

enzoh commented May 8, 2020

@kritzcreek Can you implement it? I'm perfectly okay with swapping out for more efficient implementations as they become available. Right now I just need features.

@kritzcreek
Copy link
Copy Markdown
Contributor

kritzcreek commented May 8, 2020

As I said, I don't mean to block this from being merged. I just think we ought to reserve the sortBy name for a stable sort.

I'm perfectly okay with swapping out for more efficient implementations as they become available.

It's not about efficiency, it's about correctness/semantics.

Can you implement it?

I might give it a try :)

@enzoh
Copy link
Copy Markdown
Contributor Author

enzoh commented May 8, 2020

@kritzcreek kritzcreek dismissed their stale review May 8, 2020 07:55

Issues adressed

@enzoh
Copy link
Copy Markdown
Contributor Author

enzoh commented May 8, 2020

I would prefer to not have more than one sort function in the API. So, if the preservation of these semantics is a requirement, which is perfectly fine, then lets get the merge sort implemented. I need this to implement the key space module for my DHT.

@matthewhammer
Copy link
Copy Markdown
Contributor

I think it's okay to have a non-stable sort for now if we make an issue to track this fact.

@matthewhammer
Copy link
Copy Markdown
Contributor

Alternatively (in place of implementing sorting), you can build a Red-Black tree and then just iterate it using the basic API.

Copy link
Copy Markdown
Contributor

@matthewhammer matthewhammer left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This PR seems like it could be much worse than O(n log n) on common inputs.

Can this PR just use the red-black tree instead? (For loop over array elements, inserting them; then, iterate over the elements to get the sorted order in a buffer, etc.)

@enzoh
Copy link
Copy Markdown
Contributor Author

enzoh commented May 12, 2020

The red-black tree module depends on the iterator module, which depends on this module, so no, I don't think that would work from a dependency standpoint.

@nomeata
Copy link
Copy Markdown
Contributor

nomeata commented May 12, 2020

You can have Array/Internal.mo without sort, use that in Iterator, and then re-export the internal parts in Array.mo to break such cycles.

@ggreif ggreif force-pushed the master branch 2 times, most recently from d52aecd to 08507fc Compare October 21, 2022 12:22
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants