Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

What about #sort ? #12

Open
c69 opened this issue Mar 16, 2018 · 5 comments
Open

What about #sort ? #12

c69 opened this issue Mar 16, 2018 · 5 comments

Comments

@c69
Copy link

c69 commented Mar 16, 2018

As per previous discussions, Set and Map have the inherrent order (insertion order).

Its possible to control it at creation time (by sorting initial iterable), but its not easy to change the order afterwards.

This proposal does not mention sort for neither of Map or Set, - but maybe this is a valid operation for both collection ?

If this has been discussed before - feel free to close this issue

@zloirock
Copy link
Contributor

.reduce is one of the most universal methods, .join is useful, for example, for conversion to JSON. But what's the use case of .sort on those collections?

@ljharb
Copy link
Member

ljharb commented Mar 17, 2018

I can see the value in determining iteration order - masking insertion order, for example, or having a Set subclass that maintains a sorting order.

@c69
Copy link
Author

c69 commented Mar 17, 2018

One of the use cases is when you add element, but want to preserve order of previous one (say by having "position" property on each object in the set).

Another is just plain alphanumeric sorted abstract toString operation, which is useful (ironically) when converting to JSON.

Again.. this discussion seems to be running in circles and i think that the issue with need for reduce to exist on Set and Map is caused more by lack of function composition (or piping) in JS, than by inherent need of Set / Map collection.
Because the only way to write a fluent call now is to wrap left subexpression in new Set(_) round brackets and/or spread [..._] square brackets. For join i believe the main rationale is that current output of Set.toString and @@toJson operations is useless.

Anyway, lets see examples (with inline comments).

Conversion to JSON:

// lets transfer an object with .id and .relatedItems being set of unique ids
const myDTO = {
  id: 42,
  relatedItems: new Set(1,4,2,3,5,5,4)
};
// now i just want a sorted list of numbers converted to array and then to string
let notSoFast = JSON.stringify(myDTO); // obviously does not work
let butJsonHasStringifierArg = JSON.stringify(myDTO, ' ', function (k, v) {
  if (v.toString === '[object Set]') {
    // at this point, do i actually care for difference between
    return [...v].sort().toString(); // wait - did i just killed my numbers ??
   // or supposedly easier
    return v.join(); // which does not sort (and kills numbers)
   // and so what i really want is 
    return [...v].sort();
   // which (even if .sort is added) could NOT be simplified to
    return v.sort(); // because v will be ruined anyway
  }
});

Another one, order.

const s1 = new Set(1,2,3,5); // ordered
s1.delete(2); // still ordered
s1.add(2); // oops

const s2 = new Set([2,3,5]); // ordered
s2.add(1); // oops

let sorted1 = new Set([...s1.add(4)].sort()); // current syntax
let sorted2 = s2.add(4).sort(); // bright future strawman

P.S.: i don't know the implementation details, and maybe all Sets in JS are actually something like java LinkedHashSet (and that's why they only maintain insertion order). If adding .sort will slow the implementation - again, feel free to close the issue.

@sholladay
Copy link

sholladay commented Nov 14, 2019

I am working on an HTTP router where "static" routes (i.e. ones where the path is a simple string with no parameters) are stored in a Map so that lookup for each request is O(1) (very fast) within that part of the routing table.

However, I'd like to make it so that when external tooling accesses the routing table to display it via a webpage, for example, then the table should be in a specific order for readability. In other words, I want the display order to be independent of the insertion order. It would be much more ergonomic to sort the Map than to convert it to an array first with [...map.entries()], which looks funky and takes a moment to understand, plus you then have to sort based on nested values within the array of arrays. It's icky.

@yvele
Copy link

yvele commented May 27, 2022

Looks like many developers needs a way to sort a Set directly without transforming the set to an array:

Given that a Set is ordered:

You can iterate through the elements of a set in insertion order.

We could add:

Set.prototype.sort(compareFn)

With optional compareFn like how Array.prototype.sort() is doing.

Of course Set.prototype.sort() will return a new sorted Set of the same size.

Unoptimized workaround could be:

const sortedSet = new Set(Array.from(set).sort());

My use case if for orderer unique items.

See also:

PS: I've created an issue on tc39/proposal-set-methods but I think it fits better here.

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

No branches or pull requests

5 participants