proposal-array-unique icon indicating copy to clipboard operation
proposal-array-unique copied to clipboard

Can this be more general?

Open sffc opened this issue 5 years ago • 9 comments

As others have pointed out, we already have [...new Set(array)] for primitives. So, I think that the question this proposal is addressing can be generalized to, "use something other than === to find duplicate objects in a Set".

Here are a couple other potential ways to solve this problem off the top of my head (I haven't thought them through; these are just ideas):

  • [...new Set(array, { comparator: (a, b) => a.id === b.id })] -- this would set a comparator on the Set to be used for all future additions to that specific Set.
  • Object.prototype[@@setKey] -- if present on an object, [@@setKey] should be used instead of the object pointer when checking for equality in the Set.

sffc avatar Jul 15 '20 07:07 sffc

https://github.com/tc39/proposal-collection-normalization seems relevant.

ljharb avatar Jul 15 '20 15:07 ljharb

@ljharb It seems collection normalization will convert the values but unique proposal will not.

hax avatar Jul 18 '20 17:07 hax

What i mean is, that approach could be used for a new collection hook that override the comparator (which defaults to SameValueZero)

ljharb avatar Jul 18 '20 19:07 ljharb

Not sure how it could be used to override the comparator --- As I understand, it's not override the comparator but just change the values, so u may need a map to keep the mappings from the converted values to original values.

hax avatar Jul 18 '20 20:07 hax

The normalization proposal can not, you’re correct. I’m suggesting the approach of “an options bag passed to the constructor that allows overriding internal algorithms”.

ljharb avatar Jul 18 '20 21:07 ljharb

So it would be new Set(array, { comparator: (a, b) => a.id === b.id }) just as @sffc suggested? But as I understand, to make such usage efficient, very likely we finally also need write something close to hashCode. And if that, it likely we need container type or equal/hash protocol anyway, and make normalization not very useful 😅

hax avatar Jul 19 '20 01:07 hax

I’m not sure why it wouldn’t be efficient as-is.

ljharb avatar Jul 19 '20 02:07 ljharb

This is exactly what I thought when I read "new Set(array) in ECMAScript 6 isn't enough for Non-primitive values" in the readme.

@hax No, it would be Array.from(new Map(array.map(x=>[x,x]), { coerceKey: x => x.id }).values()) or hopefully Array.from(new Set(array, { coerceKey: x => x.id })). An arbitrary comparator (not even an ordering one but just an equivalence one) cannot be used for efficient lookup.

bergus avatar Jul 28 '20 18:07 bergus

I’m not sure why it wouldn’t be efficient as-is.

@ljharb Because comparator could be complex (eg. deep equal).

@bergus I think we have similar thought about that. comparator by itself can't be efficient, but comparator + hashCode could. To some degree, coerceKey is like a stronger hashCode which never have collisions.

hax avatar Aug 13 '20 13:08 hax