adamhooper / js-sorted-set

Sorted set data structures in JavaScript

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Difference between comparing and sorting

wmertens opened this issue · comments

I notice that when you return 0 in the comparator, the items are considered equal, but instead they should provide a stable sort.

Perhaps there should be a separate isEqual option, defaulting to ===?

Can you please point to other sorted-set implementations out there that allow equal-but-different items?

A sorted set can't mimic ECMA Set completely. The performance guarantees are different. My hunch is that a sorted set with equal-but-different items stably sorted can't have any performance guarantees. Am I wrong?

I'm thinking that you can implement the stable-sorting insertion by a wrapper that augments the object with the lifetime insertion count, so that part would have the same performance guarantees.

Checking for existence of an object would indeed become O(n) for the equally-sorted leaf nodes :-/

I imagine a regular Set is implemented as a tree based on an internal object id. So in order to speed up leaf lookups, WeakSet could be used whenever there's a sorting collision. Not sure what the memory implications are, and that would only work if isEqual is just ===.

Perhaps the sanest thing to do is just to explain the performance hit and let the user choose if they accept it or change their comparator. (which is what I ended up doing)

Okay, since you've found a solution I'm going to close this issue.

I've done about 10min of searching for "stable sorted set", and all I can find are docs for sorted sets (Scala, Java, C#, Clojure, ....) that use comparators. For instance, Java 8 docs:

It is strongly recommended (though not required) that natural orderings be consistent with equals. This is so because sorted sets (and sorted maps) without explicit comparators behave "strangely" when they are used with elements (or keys) whose natural ordering is inconsistent with equals. In particular, such a sorted set (or sorted map) violates the general contract for set (or map), which is defined in terms of the equals method.

Sets aren't my day job, but I think "stable sort" in the context of a sorted set is not something widely understood -- or ever needed. Indeed, the notions of "insert" and "stable sort" are distinct -- except that you can perform one and then the other....

If you want to insert "equal-but-different" objects in a SortedSet, wrap each object: { insertOrder: 1, value: value }. Then you can create a comparator that compares the values and looks to insertOrder in the case of a tie. Nobody will be confused about why you are doing this.

Understood and makes sense, but for future reference, in order to have a working contains, the comparator must also ignore a missing insertOrder in a way that makes it walk all the collisions. Not sure if that's possible since the comparisions are transitive?

That's right. Objects are either equal or they aren't :).