Array.prototype.toObjectByProperty( element=>element.property )

classic Classic list List threaded Threaded
82 messages Options
12345
Reply | Threaded
Open this post in threaded view
|

Array.prototype.toObjectByProperty( element=>element.property )

Naveen Chawla
I've often needed to cache array elements by a unique key each element has, for quick access.

This is a shortcut:

```javascript
const elementsById = elements.toObjectByProperty(element=>element.id);
```

Support?

_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

Re: Array.prototype.toObjectByProperty( element=>element.property )

Lachlan Hunt
On 2017-08-05 20:18, Naveen Chawla wrote:
> I've often needed to cache array elements by a unique key each element has,
> for quick access.
>
> This is a shortcut:
>
> ```javascript
> const elementsById = elements.toObjectByProperty(element=>element.id);
> ```

That looks like what Array.prototype.map can already do.

--
Lachlan Hunt
https://lachy.id.au/
_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

Re: Array.prototype.toObjectByProperty( element=>element.property )

T.J. Crowder-2
In reply to this post by Naveen Chawla
On Sat, Aug 5, 2017 at 11:18 AM, Naveen Chawla
> I've often needed to cache array elements by a unique key each
> element has, for quick access.

Yes, please. I've needed this in every codebase I've ever worked on. For me, having it in the standard lib would be a win. (Yes, you can easily do it by (ab)using `reduce`, but A) It's arguably an abusage [one I'm increasingly resigning myself to], and B) Why keep re-writing it?)

Some off-the-cuff suggestions:

1. Put it on `Object`: `Object.from`.

2. Have a Map version: `Map.from`.

3. Accept any iterable, not just an array.

4. Accept a string, Symbol, or callback: If a string or Symbol, use the matching property as the key for the result. If a callback, use the callback's return value (your example).

5. Optionally accept the object or map rather than creating a new one.

So something like:

`Object.from(iterable, indexer, target = Object.create(null))`

and

`Map.from(iterable, indexer, target = new Map)`

-- T.J. Crowder

_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

Re: Array.prototype.toObjectByProperty( element=>element.property )

T.J. Crowder-2
In reply to this post by Lachlan Hunt
On Sat, Aug 5, 2017 at 12:22 PM, Lachlan Hunt
>
> On 2017-08-05 20:18, Naveen Chawla wrote:
>>
>> I've often needed to cache array elements by a unique key each
>> element has, for quick access.
>>
>
> That looks like what Array.prototype.map can already do.

No, the end result is an object, not an array. It probably would have helped if Naveen had included an example. Here I'm using `Object.from` (see my previous email) rather than `toObjectByProperty`:

```js
const a = [{id: "tjc", name: "T.J. Crowder"}, {id: "nc", name: "Naveen Chawla"}, {id: "lh", name: "Lachlan Hunt"}];
const index = Object.from(a);
console.log(index);
```

would yield:

```
{
    tjc: {id: "tjc", name: "T.J. Crowder"},
    nc: {id: "nc", name: "Naveen Chawla"},
    lh: {id: "lh", name: "Lachlan Hunt"}
}
```

-- T.J. Crowder

_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

Re: Array.prototype.toObjectByProperty( element=>element.property )

T.J. Crowder-2
On Sat, Aug 5, 2017 at 12:41 PM, T.J. Crowder
<[hidden email]> wrote:

Apologies, better proofreading required, left out the `"id"` argument:

```js
const a = [{id: "tjc", name: "T.J. Crowder"}, {id: "nc", name: "Naveen
Chawla"}, {id: "lh", name: "Lachlan Hunt"}];
const index = Object.from(a, "id");
console.log(index);
```

-- T.J. Crowder
_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

Re: Array.prototype.toObjectByProperty( element=>element.property )

Lachlan Hunt
On 2017-08-05 21:47, T.J. Crowder wrote:

> On Sat, Aug 5, 2017 at 12:41 PM, T.J. Crowder
> <[hidden email]> wrote:
>
> Apologies, better proofreading required, left out the `"id"` argument:
>
> ```js
> const a = [{id: "tjc", name: "T.J. Crowder"}, {id: "nc", name: "Naveen
> Chawla"}, {id: "lh", name: "Lachlan Hunt"}];
> const index = Object.from(a, "id");
> console.log(index);
> ```

OK, I misunderstood the original request. But even so, as you noted in
your previous mail, Array.prototype.reduce can handle it.

     a.reduce((obj, value) => (obj[value.id] = value, obj), {})

But basically, is the proposal for a native version of Lodash's
_.keyBy() method?

https://lodash.com/docs/#keyBy

--
Lachlan Hunt
https://lachy.id.au/
_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

Re: Array.prototype.toObjectByProperty( element=>element.property )

T.J. Crowder-2
On Sat, Aug 5, 2017 at 1:05 PM, Lachlan Hunt
> But basically, is the proposal for a native version of Lodash's
> `_.keyBy()` method?

Well, that's how I read it, yes; along those lines anyway.

-- T.J. Crowder


_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

Re: Array.prototype.toObjectByProperty( element=>element.property )

kdex
In reply to this post by T.J. Crowder-2
Inline.

On Saturday, August 5, 2017 1:35:35 PM CEST T.J. Crowder wrote:

> On Sat, Aug 5, 2017 at 11:18 AM, Naveen Chawla
>
> <[hidden email]> wrote:
> > I've often needed to cache array elements by a unique key each
> > element has, for quick access.
>
> Yes, please. I've needed this in every codebase I've ever worked on. For
> me, having it in the standard lib would be a win. (Yes, you can easily do
> it by (ab)using `reduce`, but A) It's arguably an abusage [one I'm
> increasingly resigning myself to], and B) Why keep re-writing it?)
Why do you consider this an abuse of `reduce`? The problem at hand is to
reduce an iterable to a single value with certain properties. And I would like
to think that reducing is what `reduce` is supposed to do. ;)

Could you please elaborate on that?

>
> Some off-the-cuff suggestions:
>
> 1. Put it on `Object`: `Object.from`.
>
> 2. Have a Map version: `Map.from`.
>
> 3. Accept any iterable, not just an array.
>
> 4. Accept a string, Symbol, or callback: If a string or Symbol, use the
> matching property as the key for the result. If a callback, use the
> callback's return value (your example).
>
> 5. Optionally accept the object or map rather than creating a new one.
>
> So something like:
>
> `Object.from(iterable, indexer, target = Object.create(null))`
>
> and
>
> `Map.from(iterable, indexer, target = new Map)`
>
> -- T.J. Crowder
_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss

signature.asc (849 bytes) Download Attachment
Reply | Threaded
Open this post in threaded view
|

Re: Array.prototype.toObjectByProperty( element=>element.property )

T.J. Crowder-2
On Sat, Aug 5, 2017 at 3:08 PM, kdex <[hidden email]> wrote:
> Could you please elaborate on that?

It's not important here. :-) I've replied off-list. (If anyone feels strongly that the reply is relevant, let me know and I'll repost it to the list, but...)

-- T.J. Crowder


_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

Re: Re: Array.prototype.toObjectByProperty( element=>element.property )

Darien Valentine
In reply to this post by Naveen Chawla
FWIW, while I find needs like this common, too, where Map is sensible instead of
Object, it does come out pretty clean:

```
const a = [
  {id: "tjc", name: "T.J. Crowder"},
  {id: "nc", name: "Naveen Chawla"},
  {id: "lh", name: "Lachlan Hunt"}
];

const index = new Map(a.map(member => [ member.name, member ]));
```

Although I’m also puzzled by the suggestion that reducing to an object is an abuse,
I do find I wish there were a complement to `Object.entries`:

```
// Object to pairs, and therefore map, is simple:

const map = new Map(Object.entries(obj));

// Converting back is also simple ... but not exactly expressive:

[ ...map ].reduce((acc, [ key, val ]) => Object.assign(acc, { [key]: val }));
```

Something like `Object.fromEntries` would not provide as much sugar for the
OP case as `toObjectByProperty`, but it gets pretty close and has the advantage
of being more generic; `toObjectByProperty` strikes me as rather specific for a
built-in, especially since one might want to map by a derived value rather than
a property. Both map<->object and array<->object cases would become more
expressive — plus it follows pretty naturally from the existence of
`Object.entries` that there might be a reverse op.

```
Object.fromEntries(a.map(a.map(member => [ member.name, member ])));
```

In other words, `Object.fromEntries(Object.entries(obj))` would be equivalent in
effect to `Object.assign({}, obj)`.

Would that adequately address this case you think? My sense is that it’s better to supply generic helpers before more specific helpers when it comes to built-ins.

_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

Re: Re: Array.prototype.toObjectByProperty( element=>element.property )

Isiah Meadows-2
I have a better idea: how about `Object.from(iter)`, where `iter` is
an iterable of `[key, value]` pairs?

```
const a = [
  {id: "tjc", name: "T.J. Crowder"},
  {id: "nc", name: "Naveen Chawla"},
  {id: "lh", name: "Lachlan Hunt"}
];

const object = Object.from(a.map(o => [o.id, o.name]))
```

We already have `Object.entries(object)`, returning an array of `[key,
value]` pairs, so this would effectively be the inverse of that -
`Object.from(Object.entries(object))` would be equivalent to
`Object.assign({}, object)` assuming native prototypes are unmodified.

(Yes, it's like `_.zipObject(pairs)` from Lodash)
-----

Isiah Meadows
[hidden email]

Looking for web consulting? Or a new website?
Send me an email and we can get started.
www.isiahmeadows.com


On Sat, Aug 5, 2017 at 4:42 PM, Darien Valentine <[hidden email]> wrote:

> FWIW, while I find needs like this common, too, where Map is sensible
> instead of
> Object, it does come out pretty clean:
>
> ```
> const a = [
>   {id: "tjc", name: "T.J. Crowder"},
>   {id: "nc", name: "Naveen Chawla"},
>   {id: "lh", name: "Lachlan Hunt"}
> ];
>
> const index = new Map(a.map(member => [ member.name, member ]));
> ```
>
> Although I’m also puzzled by the suggestion that reducing to an object is an
> abuse,
> I do find I wish there were a complement to `Object.entries`:
>
> ```
> // Object to pairs, and therefore map, is simple:
>
> const map = new Map(Object.entries(obj));
>
> // Converting back is also simple ... but not exactly expressive:
>
> [ ...map ].reduce((acc, [ key, val ]) => Object.assign(acc, { [key]: val
> }));
> ```
>
> Something like `Object.fromEntries` would not provide as much sugar for the
> OP case as `toObjectByProperty`, but it gets pretty close and has the
> advantage
> of being more generic; `toObjectByProperty` strikes me as rather specific
> for a
> built-in, especially since one might want to map by a derived value rather
> than
> a property. Both map<->object and array<->object cases would become more
> expressive — plus it follows pretty naturally from the existence of
> `Object.entries` that there might be a reverse op.
>
> ```
> Object.fromEntries(a.map(a.map(member => [ member.name, member ])));
> ```
>
> In other words, `Object.fromEntries(Object.entries(obj))` would be
> equivalent in
> effect to `Object.assign({}, obj)`.
>
> Would that adequately address this case you think? My sense is that it’s
> better to supply generic helpers before more specific helpers when it comes
> to built-ins.
>
> _______________________________________________
> es-discuss mailing list
> [hidden email]
> https://mail.mozilla.org/listinfo/es-discuss
>
_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

Re: Re: Array.prototype.toObjectByProperty( element=>element.property )

Jordan Harband
If anything *were* to be added, it would surely be a static method that took an iterable of entries and returned an object, and it would surely have the semantic that `new Set(Object.entries(thisThing(entries)))` and `new Set(entries)` were two conceptually equal sets (iow, that each corresponding entry's key were ===, modulo ToPropertyKey conversion, and each corresponding entry's value were ===).

I'm not necessarily proposing this at all or any time soon, but one thing that *would* help me or a future champion (if proposed) is if interested parties wrote up a convincing proposal readme - rationale, similar patterns in the ecosystem, motivating use cases, etc.

On Sun, Aug 6, 2017 at 11:31 AM, Isiah Meadows <[hidden email]> wrote:
I have a better idea: how about `Object.from(iter)`, where `iter` is
an iterable of `[key, value]` pairs?

```
const a = [
  {id: "tjc", name: "T.J. Crowder"},
  {id: "nc", name: "Naveen Chawla"},
  {id: "lh", name: "Lachlan Hunt"}
];

const object = Object.from(a.map(o => [o.id, o.name]))
```

We already have `Object.entries(object)`, returning an array of `[key,
value]` pairs, so this would effectively be the inverse of that -
`Object.from(Object.entries(object))` would be equivalent to
`Object.assign({}, object)` assuming native prototypes are unmodified.

(Yes, it's like `_.zipObject(pairs)` from Lodash)
-----

Isiah Meadows
[hidden email]

Looking for web consulting? Or a new website?
Send me an email and we can get started.
www.isiahmeadows.com


On Sat, Aug 5, 2017 at 4:42 PM, Darien Valentine <[hidden email]> wrote:
> FWIW, while I find needs like this common, too, where Map is sensible
> instead of
> Object, it does come out pretty clean:
>
> ```
> const a = [
>   {id: "tjc", name: "T.J. Crowder"},
>   {id: "nc", name: "Naveen Chawla"},
>   {id: "lh", name: "Lachlan Hunt"}
> ];
>
> const index = new Map(a.map(member => [ member.name, member ]));
> ```
>
> Although I’m also puzzled by the suggestion that reducing to an object is an
> abuse,
> I do find I wish there were a complement to `Object.entries`:
>
> ```
> // Object to pairs, and therefore map, is simple:
>
> const map = new Map(Object.entries(obj));
>
> // Converting back is also simple ... but not exactly expressive:
>
> [ ...map ].reduce((acc, [ key, val ]) => Object.assign(acc, { [key]: val
> }));
> ```
>
> Something like `Object.fromEntries` would not provide as much sugar for the
> OP case as `toObjectByProperty`, but it gets pretty close and has the
> advantage
> of being more generic; `toObjectByProperty` strikes me as rather specific
> for a
> built-in, especially since one might want to map by a derived value rather
> than
> a property. Both map<->object and array<->object cases would become more
> expressive — plus it follows pretty naturally from the existence of
> `Object.entries` that there might be a reverse op.
>
> ```
> Object.fromEntries(a.map(a.map(member => [ member.name, member ])));
> ```
>
> In other words, `Object.fromEntries(Object.entries(obj))` would be
> equivalent in
> effect to `Object.assign({}, obj)`.
>
> Would that adequately address this case you think? My sense is that it’s
> better to supply generic helpers before more specific helpers when it comes
> to built-ins.
>
> _______________________________________________
> es-discuss mailing list
> [hidden email]
> https://mail.mozilla.org/listinfo/es-discuss
>
_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss


_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

Re: Re: Array.prototype.toObjectByProperty( element=>element.property )

Darien Valentine
In reply to this post by Naveen Chawla
@Isiah I think you and I just described the identical thing (except that I’d put `fromEntries` where you put `from`) — and it’s a subset of the overloaded proposed solution from Crowder above. That three people responded with the same thing or a variation of it suggests that this is indeed a gap where a thing intuitively ought to exist.

@Harband Unless somebody else wants to, I’d be interested in trying my hand at assembling a proper proposal. I think I’ve spent enough time in the spec & various proposals at this point that I might not totally butcher it.

_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

Re: Re: Array.prototype.toObjectByProperty( element=>element.property )

Darien Valentine
Awesome. I didn’t know about the upcoming template, so I may have jumped the gun haha:


It’s quite primitive though, no formal algorithm / ecmarkup or anything. I’ll keep an eye on the template project and update accordingly once that’s ready, thanks.

_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

Re: Re: Array.prototype.toObjectByProperty( element=>element.property )

T.J. Crowder-2
On Sat, Aug 5, 2017 at 9:42 PM, Darien Valentine
<[hidden email]> wrote:

> FWIW, while I find needs like this common, too, where Map is sensible
> instead of
> Object, it does come out pretty clean:
>
> ```
> const a = [
>   {id: "tjc", name: "T.J. Crowder"},
>   {id: "nc", name: "Naveen Chawla"},
>   {id: "lh", name: "Lachlan Hunt"}
> ];
>
> const index = new Map(a.map(member => [ member.name, member ]));
> ```

And:

On Sun, Aug 6, 2017 at 7:31 PM, Isiah Meadows
<[hidden email]> wrote:
> I have a better idea: how about `Object.from(iter)`, where `iter` is
> an iterable of `[key, value]` pairs?

For the common case I have, that would require an additional transform
producing a lot of unnecessary temporary objects. I basically never
have `[ [key, value], [key, value] ...]` as my starting point where I
want this.

On Sat, Aug 5, 2017 at 9:42 PM, Darien Valentine
<[hidden email]> wrote:
> Although I’m also puzzled by the suggestion that reducing to an object is an
> abuse...

Let's ignore that, sorry; it's purely a distraction in this conversation.

> `toObjectByProperty` strikes me as rather specific for a built-in,
> especially since one might want to map by a derived value rather
> than a property.

Naveen's original post shows a callback that returns the key to use. I
also flag up using a callback to determine the value in my earlier
post on this. (In my post, I cater to the common case of a specific
property known in advance, but also allow for a callback; like
`String#replace`'s second parameter.)

> Would that adequately address this case you think?

For me, no; an unnecessary additional transform and too much memory churn.

> My sense is that it’s better to supply generic helpers before
> more specific helpers when it comes to built-ins.

In general, absolutely. But where the abstraction takes us into
unnecessary complexity and performance degradation, *slightly* more
specificity is fine in my view. I don't think my suggested
`Object.from` and `Map.from` are too specific.

-- T.J. Crowder
_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

Re: Re: Array.prototype.toObjectByProperty( element=>element.property )

Darien Valentine
For me, no; an unnecessary additional transform and too much memory churn.

Interesting. I’ve included a note in the 'concerns' section on that proposal regarding the possibility of accepting a mapping function (like `Array.from`). That could avoid the extra array creation. However I suspect the idea of accepting a string or symbol key rather than a function is unlikely to gain traction — for one, there’s nothing like it presently in the many places there _could_ be, and perhaps more importantly, that overloading represents an additional cost for every use case, even if it might reduce the cost for one. We’re talking very small perf differences here of course, but one of the reasons many lodash tools are not particularly fast is the overhead that comes from supporting heavy overloading.

Assuming that proposal isn’t a flop, please feel free to open an issue on the repo making the case for the map argument (in whatever form) — that could help measure whether that’s something most people expect to see.

On Mon, Aug 7, 2017 at 5:58 AM, T.J. Crowder <[hidden email]> wrote:
On Sat, Aug 5, 2017 at 9:42 PM, Darien Valentine
<[hidden email]> wrote:
> FWIW, while I find needs like this common, too, where Map is sensible
> instead of
> Object, it does come out pretty clean:
>
> ```
> const a = [
>   {id: "tjc", name: "T.J. Crowder"},
>   {id: "nc", name: "Naveen Chawla"},
>   {id: "lh", name: "Lachlan Hunt"}
> ];
>
> const index = new Map(a.map(member => [ member.name, member ]));
> ```

And:

On Sun, Aug 6, 2017 at 7:31 PM, Isiah Meadows
<[hidden email]> wrote:
> I have a better idea: how about `Object.from(iter)`, where `iter` is
> an iterable of `[key, value]` pairs?

For the common case I have, that would require an additional transform
producing a lot of unnecessary temporary objects. I basically never
have `[ [key, value], [key, value] ...]` as my starting point where I
want this.

On Sat, Aug 5, 2017 at 9:42 PM, Darien Valentine
<[hidden email]> wrote:
> Although I’m also puzzled by the suggestion that reducing to an object is an
> abuse...

Let's ignore that, sorry; it's purely a distraction in this conversation.

> `toObjectByProperty` strikes me as rather specific for a built-in,
> especially since one might want to map by a derived value rather
> than a property.

Naveen's original post shows a callback that returns the key to use. I
also flag up using a callback to determine the value in my earlier
post on this. (In my post, I cater to the common case of a specific
property known in advance, but also allow for a callback; like
`String#replace`'s second parameter.)

> Would that adequately address this case you think?

For me, no; an unnecessary additional transform and too much memory churn.

> My sense is that it’s better to supply generic helpers before
> more specific helpers when it comes to built-ins.

In general, absolutely. But where the abstraction takes us into
unnecessary complexity and performance degradation, *slightly* more
specificity is fine in my view. I don't think my suggested
`Object.from` and `Map.from` are too specific.

-- T.J. Crowder


_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

Re: Re: Array.prototype.toObjectByProperty( element=>element.property )

T.J. Crowder-2
On Mon, Aug 7, 2017 at 2:23 PM, Darien Valentine
> > For me, no; an unnecessary additional transform and too much.
> > memory churn.
>
> However I suspect the idea of accepting a string or symbol key
> rather than a function is unlikely to gain traction — for one,
> there’s nothing like it presently in the many places there
> _could_ be

Where are you thinking of?

> ...and perhaps more importantly, that overloading represents an
> additional cost for every use case, even if it might reduce the
> cost for one.

That's a fair concern, although the test is trivially simple and very fast. I'll flag up again the precedent of `String#replace`. In my experience, the string use case is overwhelmingly the common one. So slowing down the common case because of edge cases outweighs that concern for me. In spec terms, I'd test first for string, then function, then Symbol. (In polyfill terms, it'd be a `switch` on `typeof`.)

> Assuming that proposal isn’t a flop, please feel free to open an
> issue on the repo making the case for the map argument...

I don't think your `Object.fromEntries` isn't similar enough to what I want. I'll create a proposal for what I want in a few days after more feedback has come in.

You seem to have had some private reply about an upcoming proposal template...?

-- T.J. Crowder


_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

Re: Re: Array.prototype.toObjectByProperty( element=>element.property )

Darien Valentine
Where are you thinking of? [re: other methods that could take overloaded/shorthand map/predicate args, but do not]

These could also accept strings for property mapping in the same manner you proposed, but do not currently:

- `Array.from`
- `Array.prototype.every`
- `Array.prototype.filter`
- `Array.prototype.map`
- `Array.prototype.some`
- `new Map`
- `new Set`

Mind, I’m not arguing that it isn’t a useful idea. Where lodash has equivalents for the above, strings are permitted, and I’m sure people make use of that functionality.

I think the spot where we might disagree is the assessment that "the string case is overwhelmingly the common one." This doesn’t sound quite right to me. That’s not been true in my experience, though I don’t have any data to say concretely one way or another. In any case, I’m not out to block anything if smarter people think it’s a good idea.

 I'll create a proposal for what I want in a few days after more feedback has come in.

Would you consider the method you’ll be proposing to be "instead of" a reverse-of-object-entries type proposal, or is it orthogonal to that?

You seem to have had some private reply about an upcoming proposal template...?

Yeah — it doesn’t exist yet, however.

On Mon, Aug 7, 2017 at 9:46 AM, T.J. Crowder <[hidden email]> wrote:
On Mon, Aug 7, 2017 at 2:23 PM, Darien Valentine
> > For me, no; an unnecessary additional transform and too much.
> > memory churn.
>
> However I suspect the idea of accepting a string or symbol key
> rather than a function is unlikely to gain traction — for one,
> there’s nothing like it presently in the many places there
> _could_ be

Where are you thinking of?

> ...and perhaps more importantly, that overloading represents an
> additional cost for every use case, even if it might reduce the
> cost for one.

That's a fair concern, although the test is trivially simple and very fast. I'll flag up again the precedent of `String#replace`. In my experience, the string use case is overwhelmingly the common one. So slowing down the common case because of edge cases outweighs that concern for me. In spec terms, I'd test first for string, then function, then Symbol. (In polyfill terms, it'd be a `switch` on `typeof`.)

> Assuming that proposal isn’t a flop, please feel free to open an
> issue on the repo making the case for the map argument...

I don't think your `Object.fromEntries` isn't similar enough to what I want. I'll create a proposal for what I want in a few days after more feedback has come in.

You seem to have had some private reply about an upcoming proposal template...?

-- T.J. Crowder



_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

Re: Re: Array.prototype.toObjectByProperty( element=>element.property )

T.J. Crowder-2
On Mon, Aug 7, 2017 at 4:17 PM, Darien Valentine
>
> > Where are you thinking of? [re: other methods that could take overloaded/shorthand map/predicate args, but do not]
>
> These could also accept strings for property mapping in the same manner you proposed, but do not currently:
>
> - `Array.from`
> - `Array.prototype.every`
> - ...

I think it comes down to what the majority use case is. For most of those I've never used just a single property access. But I certainly have for `map` and `filter`, I see your point there. It's not been anything like my majority use case for those two, but definitely not rare.

> I think the spot where we might disagree is the assessment that
> "the string case is overwhelmingly the common one." This doesn’t
> sound quite right to me. That’s not been true in my experience...

:-) Your mileage may vary, but I'm surprised by that; surely you use maps keyed by a property of the object they map to? The times I've wanted to *generate* the key rather than just pluck it can be counted on one *finger* (since `Object.create`; prior to that, I was prefixing names in index objects to avoid `Object.prototype` collisions, back in the day). Whereas wanting to use an existing property as the index key I've done hundreds of times if not more. For instance, an app with a list of...well, almost anything, where I want access both as a list (for iteration; showing the list) and random access by ID (for showing details in response to a pick).

> > I'll create a proposal for what I want in a few days after more
> > feedback has come in.
>
> Would you consider the method you’ll be proposing to be "instead
> of" a reverse-of-object-entries type proposal, or is it
> orthogonal to that?

Ortogonal I think. Your `Object.fromEntries` works with an iterable of `[key, value]` pairs (or, I'm guessing, a callback that can produce `[key, value]` pairs). My `Object.from` works with an iterable of any kind of object where the object itself is expected to be the value. I think trying to shoehorn both in to one function would over-complicate it.

-- T.J. Crowder

_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

Re: Re: Array.prototype.toObjectByProperty( element=>element.property )

Naveen Chawla
In reply to this post by Darien Valentine
Hi Darien!

The concept of using a 2-element array to represent a key and value is unique to Maps and if I'm not mistaken, exists purely because there wasn't a tight, compact alternative that could house a key and value where the key could be an object.

However, if we are going straight from iterable to Object, I don't think we should be propagating the "[key, value] as an array" pattern. It's unclean partly because it's 2 elements max and IDEs can't inherently show warnings if you accidentally added more, unless it has some intelligence about the method itself. Partly also because the arrays are not immediately readable unless you already know the that the arrays mean [key, value].

I'm not convinced that Maps have any real value at all right now vs objects (despite what the documentation says): currently they only offer the ability to have objects as keys but without custom key equality (only ===), and you lose the elegant square bracket syntax for accessing elements, among other things, so it's unclear to me how compelling the use of Maps vs objects is at all in real world scenarios, so I'm not sure anything about Maps should be a pattern for other language features.

Iterables are very generic, since they can include generators, sets etc. Objects are a fundamental construct, so it makes sense to be able to cleanly transition between these structures.

Adding the idea to iterable in general (instead of just Array) would look like e.g.:

```
const cache = iterable.toObjectByProperty(item=>item.id)
```

On Sun, 6 Aug 2017 at 02:12 Darien Valentine <[hidden email]> wrote:
FWIW, while I find needs like this common, too, where Map is sensible instead of
Object, it does come out pretty clean:

```
const a = [
  {id: "tjc", name: "T.J. Crowder"},
  {id: "nc", name: "Naveen Chawla"},
  {id: "lh", name: "Lachlan Hunt"}
];

const index = new Map(a.map(member => [ member.name, member ]));
```

Although I’m also puzzled by the suggestion that reducing to an object is an abuse,
I do find I wish there were a complement to `Object.entries`:

```
// Object to pairs, and therefore map, is simple:

const map = new Map(Object.entries(obj));

// Converting back is also simple ... but not exactly expressive:

[ ...map ].reduce((acc, [ key, val ]) => Object.assign(acc, { [key]: val }));
```

Something like `Object.fromEntries` would not provide as much sugar for the
OP case as `toObjectByProperty`, but it gets pretty close and has the advantage
of being more generic; `toObjectByProperty` strikes me as rather specific for a
built-in, especially since one might want to map by a derived value rather than
a property. Both map<->object and array<->object cases would become more
expressive — plus it follows pretty naturally from the existence of
`Object.entries` that there might be a reverse op.

```
Object.fromEntries(a.map(a.map(member => [ member.name, member ])));
```

In other words, `Object.fromEntries(Object.entries(obj))` would be equivalent in
effect to `Object.assign({}, obj)`.

Would that adequately address this case you think? My sense is that it’s better to supply generic helpers before more specific helpers when it comes to built-ins.
_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss

_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
12345