tc39 / proposal-array-unique

ECMAScript proposal for Deduplicating method of Array
138 stars 7 forks source link

Can this be more general? #8

Open sffc opened 4 years ago

sffc commented 4 years ago

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):

ljharb commented 4 years ago

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

hax commented 4 years ago

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

ljharb commented 4 years ago

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

hax commented 4 years ago

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.

ljharb commented 4 years ago

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”.

hax commented 4 years ago

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 😅

ljharb commented 4 years ago

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

bergus commented 4 years ago

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.

hax commented 4 years ago

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.