Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > comp.lang.javascript > #39403 > unrolled thread
| Started by | Andrew Poulos <ap_prog@hotmail.com> |
|---|---|
| First post | 2021-01-31 14:42 +1100 |
| Last post | 2021-02-03 19:42 +0100 |
| Articles | 11 — 4 participants |
Back to article view | Back to comp.lang.javascript
Referencing an object prop with a string Andrew Poulos <ap_prog@hotmail.com> - 2021-01-31 14:42 +1100
Re: Referencing an object prop with a string "Michael Haufe (TNO)" <tno@thenewobjective.com> - 2021-01-30 19:52 -0800
Re: Referencing an object prop with a string "Michael Haufe (TNO)" <tno@thenewobjective.com> - 2021-01-30 19:54 -0800
Re: Referencing an object prop with a string Andrew Poulos <ap_prog@hotmail.com> - 2021-01-31 20:29 +1100
Re: Referencing an object prop with a string H e <he12457@hotmail.com> - 2021-01-31 02:17 -0800
Re: Referencing an object prop with a string Thomas 'PointedEars' Lahn <PointedEars@web.de> - 2021-02-02 04:06 +0100
Re: Referencing an object prop with a string "Michael Haufe (TNO)" <tno@thenewobjective.com> - 2021-02-02 13:01 -0800
Re: Referencing an object prop with a string Thomas 'PointedEars' Lahn <PointedEars@web.de> - 2021-02-02 23:50 +0100
Re: Referencing an object prop with a string "Michael Haufe (TNO)" <tno@thenewobjective.com> - 2021-02-02 19:19 -0800
Re: Referencing an object prop with a string "Michael Haufe (TNO)" <tno@thenewobjective.com> - 2021-02-02 19:26 -0800
Re: Referencing an object prop with a string Thomas 'PointedEars' Lahn <PointedEars@web.de> - 2021-02-03 19:42 +0100
| From | Andrew Poulos <ap_prog@hotmail.com> |
|---|---|
| Date | 2021-01-31 14:42 +1100 |
| Subject | Referencing an object prop with a string |
| Message-ID | <Vt-dnSg5Kd2Iuov9nZ2dnUU7-Q3NnZ2d@westnet.com.au> |
Say I have an object with lots of properties eg
let o = { a: 1, a2: 1, a3: 2,... };
when I want to get a property value I send the property name to this
function
function getPropValue(obj, prop) {
return obj[prop];
}
Now I find the object also has nested properties eg
let o = { a: 1, a2: 1, a3: 2, a4: {a: 1, b: 2, c: 3...}... };
I changed the function to handle nested properties with
function getPropValue(obj, prop1, prop2) {
return prop2 == undefined ? obj[prop1] : obj[prop1][prop2];
}
But what happens if the nesting goes deeper and deeper? It'll get messy
fairly quickly. Is there a better to handle this?
Andrew Poulos
[toc] | [next] | [standalone]
| From | "Michael Haufe (TNO)" <tno@thenewobjective.com> |
|---|---|
| Date | 2021-01-30 19:52 -0800 |
| Message-ID | <5793bf43-6506-4351-bdca-3d59d740c5e5n@googlegroups.com> |
| In reply to | #39403 |
On Saturday, January 30, 2021 at 9:42:26 PM UTC-6, Andrew Poulos wrote:
> Say I have an object with lots of properties eg
>
> let o = { a: 1, a2: 1, a3: 2,... };
>
> when I want to get a property value I send the property name to this
> function
>
> function getPropValue(obj, prop) {
> return obj[prop];
> }
>
> Now I find the object also has nested properties eg
>
> let o = { a: 1, a2: 1, a3: 2, a4: {a: 1, b: 2, c: 3...}... };
>
> I changed the function to handle nested properties with
>
> function getPropValue(obj, prop1, prop2) {
> return prop2 == undefined ? obj[prop1] : obj[prop1][prop2];
> }
>
> But what happens if the nesting goes deeper and deeper? It'll get messy
> fairly quickly. Is there a better to handle this?
You can do this:
```
let walk = (o, path)=>path.split('.').reduce((o,k)=>o && o[k], o);
let o = { a: 1, a2: 1, a3: 2, a4: {a: 1, b: 2, c: 3} };
walk(o, 'a4.c')
```
[toc] | [prev] | [next] | [standalone]
| From | "Michael Haufe (TNO)" <tno@thenewobjective.com> |
|---|---|
| Date | 2021-01-30 19:54 -0800 |
| Message-ID | <a989f3f6-bb92-4920-9f1e-db70d79406e0n@googlegroups.com> |
| In reply to | #39404 |
On Saturday, January 30, 2021 at 9:52:28 PM UTC-6, Michael Haufe (TNO) wrote:
> On Saturday, January 30, 2021 at 9:42:26 PM UTC-6, Andrew Poulos wrote:
> > Say I have an object with lots of properties eg
> >
> > let o = { a: 1, a2: 1, a3: 2,... };
> >
> > when I want to get a property value I send the property name to this
> > function
> >
> > function getPropValue(obj, prop) {
> > return obj[prop];
> > }
> >
> > Now I find the object also has nested properties eg
> >
> > let o = { a: 1, a2: 1, a3: 2, a4: {a: 1, b: 2, c: 3...}... };
> >
> > I changed the function to handle nested properties with
> >
> > function getPropValue(obj, prop1, prop2) {
> > return prop2 == undefined ? obj[prop1] : obj[prop1][prop2];
> > }
> >
> > But what happens if the nesting goes deeper and deeper? It'll get messy
> > fairly quickly. Is there a better to handle this?
> You can do this:
>
> ```
> let walk = (o, path)=>path.split('.').reduce((o,k)=>o && o[k], o);
>
> let o = { a: 1, a2: 1, a3: 2, a4: {a: 1, b: 2, c: 3} };
>
> walk(o, 'a4.c')
> ```
For even more complicated structures you may want to use JsonPath:
<https://goessner.net/articles/JsonPath/>
There are packages available:
<https://www.npmjs.com/search?q=jsonpath>
[toc] | [prev] | [next] | [standalone]
| From | Andrew Poulos <ap_prog@hotmail.com> |
|---|---|
| Date | 2021-01-31 20:29 +1100 |
| Message-ID | <bZydnbkx9McK5Yv9nZ2dnUU7-XXNnZ2d@westnet.com.au> |
| In reply to | #39404 |
On 31/01/2021 2:52 pm, Michael Haufe (TNO) wrote:
> On Saturday, January 30, 2021 at 9:42:26 PM UTC-6, Andrew Poulos wrote:
>> Say I have an object with lots of properties eg
>>
>> let o = { a: 1, a2: 1, a3: 2,... };
>>
>> when I want to get a property value I send the property name to this
>> function
>>
>> function getPropValue(obj, prop) {
>> return obj[prop];
>> }
>>
>> Now I find the object also has nested properties eg
>>
>> let o = { a: 1, a2: 1, a3: 2, a4: {a: 1, b: 2, c: 3...}... };
>>
>> I changed the function to handle nested properties with
>>
>> function getPropValue(obj, prop1, prop2) {
>> return prop2 == undefined ? obj[prop1] : obj[prop1][prop2];
>> }
>>
>> But what happens if the nesting goes deeper and deeper? It'll get messy
>> fairly quickly. Is there a better to handle this?
>
>
> You can do this:
>
> ```
> let walk = (o, path)=>path.split('.').reduce((o,k)=>o && o[k], o);
>
> let o = { a: 1, a2: 1, a3: 2, a4: {a: 1, b: 2, c: 3} };
>
> walk(o, 'a4.c')
Thanks that looks to be a simple solution.
Andrew Poulos
[toc] | [prev] | [next] | [standalone]
| From | H e <he12457@hotmail.com> |
|---|---|
| Date | 2021-01-31 02:17 -0800 |
| Message-ID | <eec52782-8d9d-4dfe-b441-1b9b8404762dn@googlegroups.com> |
| In reply to | #39407 |
R e c u r s i o n is the k e y. Khrichtjan Robham y12983 ma il co m (mail . com) 372 6861327
[toc] | [prev] | [next] | [standalone]
| From | Thomas 'PointedEars' Lahn <PointedEars@web.de> |
|---|---|
| Date | 2021-02-02 04:06 +0100 |
| Message-ID | <806120824.0ifERbkFSE@PointedEars.de> |
| In reply to | #39404 |
Michael Haufe (TNO) wrote:
> let walk = (o, path)=>path.split('.').reduce((o,k)=>o && o[k], o);
This does not work if the property name contains `.'. The approach to use
Array.prototype.reduce() is an elegant one, though, and can be applied to
supporting a path array (too), which solves that problem:
let walk = (o, path) => path.reduce((o, k) => o && o[k], o);
--
PointedEars
FAQ: <http://PointedEars.de/faq> | <http://PointedEars.de/es-matrix>
<https://github.com/PointedEars> | <http://PointedEars.de/wsvn/>
Twitter: @PointedEars2 | Please do not cc me./Bitte keine Kopien per E-Mail.
[toc] | [prev] | [next] | [standalone]
| From | "Michael Haufe (TNO)" <tno@thenewobjective.com> |
|---|---|
| Date | 2021-02-02 13:01 -0800 |
| Message-ID | <ddc05c02-03b1-4600-8236-5453b413a54an@googlegroups.com> |
| In reply to | #39420 |
On Monday, February 1, 2021 at 9:07:06 PM UTC-6, Thomas 'PointedEars' Lahn wrote:
> Michael Haufe (TNO) wrote:
>
> > let walk = (o, path)=>path.split('.').reduce((o,k)=>o && o[k], o);
> This does not work if the property name contains `.'. The approach to use
> Array.prototype.reduce() is an elegant one, though, and can be applied to
> supporting a path array (too), which solves that problem:
>
> let walk = (o, path) => path.reduce((o, k) => o && o[k], o);
I wonder if a variant of JSONPath could be promoted into the language proper. I tried in the early ES5 days to convince the committee but there were bigger fish to fry at the time.
With Symbols and the spread operator, it may be harder to get a proposal through.
At least Slice Notation has a change of succeeding:
<https://github.com/tc39/proposal-slice-notation>
[toc] | [prev] | [next] | [standalone]
| From | Thomas 'PointedEars' Lahn <PointedEars@web.de> |
|---|---|
| Date | 2021-02-02 23:50 +0100 |
| Message-ID | <2081055.NgBsaNRSFp@PointedEars.de> |
| In reply to | #39423 |
Michael Haufe (TNO) wrote:
> On Monday, February 1, 2021 at 9:07:06 PM UTC-6, Thomas 'PointedEars' Lahn
> wrote:
>> Michael Haufe (TNO) wrote:
>> > let walk = (o, path)=>path.split('.').reduce((o,k)=>o && o[k], o);
>> This does not work if the property name contains `.'. The approach to use
>> Array.prototype.reduce() is an elegant one, though, and can be applied to
>> supporting a path array (too), which solves that problem:
>>
>> let walk = (o, path) => path.reduce((o, k) => o && o[k], o);
>
> I wonder if a variant of JSONPath could be promoted into the language
> proper.
Yes, I am not particularly fond of Stefan Goessners syntax choices either.
While I could perhaps live with “@” instead of “.”, coming from the command
shell I find “..” to access *subordered* items very counter-intuitive (I
also did with E4X). Why did he not propose and implement the familiar XPath
syntax? For example, I see no good reason to propose ”$” instead of “/”.
> I tried in the early ES5 days to convince the committee but there
> were bigger fish to fry at the time.
ACK.
> With Symbols and the spread operator, it may be harder to get a proposal
> through.
What exactly do you mean?
One problem I see is that there is not really a need for it anymore (or is
there?): You can write now (and at least *execute* much more efficiently)
obj?.store?.book?.filter((book) => book.price < 10)
.map((book) => book.title) || []
instead of
jsonPath(obj, '$.store.book[?(@.price < 10)].title')
Which reminds me of LINQ which solves similar problems.
> At least Slice Notation has a change of succeeding:
>
> <https://github.com/tc39/proposal-slice-notation>
Yes, I think that would be a useful and unproblematic addition.
I would even like a[-1] as in Python (seriously, is there a use-case for
properties named named “-1” in an *array*?). I added support for using
negative indexes to access elements from the end of an array in
JSX:array.js:BigArray with Proxy, and BigArray.prototype.get() to do it
in a backwards-compatible way, about 5 years ago:
<https://github.com/PointedEars/JSX/blob/e6eb05cb945df7b7304d572ccbac90ae9a632286/array.js#L491-L1158>
--
PointedEars
FAQ: <http://PointedEars.de/faq> | <http://PointedEars.de/es-matrix>
<https://github.com/PointedEars> | <http://PointedEars.de/wsvn/>
Twitter: @PointedEars2 | Please do not cc me./Bitte keine Kopien per E-Mail.
[toc] | [prev] | [next] | [standalone]
| From | "Michael Haufe (TNO)" <tno@thenewobjective.com> |
|---|---|
| Date | 2021-02-02 19:19 -0800 |
| Message-ID | <a6cd17cf-36d2-4724-9ca7-f512f7c4c03en@googlegroups.com> |
| In reply to | #39424 |
On Tuesday, February 2, 2021 at 4:50:26 PM UTC-6, Thomas 'PointedEars' Lahn wrote:
> Michael Haufe (TNO) wrote:
> > I wonder if a variant of JSONPath could be promoted into the language
> > proper.
> Yes, I am not particularly fond of Stefan Goessners syntax choices either.
> While I could perhaps live with “@” instead of “.”, coming from the command
> shell I find “..” to access *subordered* items very counter-intuitive (I
> also did with E4X). Why did he not propose and implement the familiar XPath
> syntax? For example, I see no good reason to propose ”$” instead of “/”.
I don't think either could be used:
'$' is a variable name already so that could not become a reserved work
'/' could be used as a prefix operator but with the existence of
multi-line comments: '/* ... */'
single line comments: '// ...'
and '/' as an infix division I think that would be hard to sell.
Additionally, if '/' is used as the root, it seems to want '//' as the descendant selector
like xpath. This would conflict with single line comments.
Maybe '#' as root?
> > With Symbols and the spread operator, it may be harder to get a proposal
> > through.
> What exactly do you mean?
JSONPath uses '..' as the descendant selector. The existing spread operator is '...'
With destructuring it just looks wrong. In the below example I want c to be assigned the value of c.c1.c2:
```
let {a, b, c: c..c2, ...rest} = {a: 10, b: 20, c: {c1: {c2: 30}}, d: 40, e: 50};
```
What if c2 is a Symbol?
```
let {a, b, c: c..[c2], ...rest} = {a: 10, b: 20, c: {c1: {[c2]: 30}}, d: 40, e: 50};
```
obj..[symbolName] seems a bit terse...
> One problem I see is that there is not really a need for it anymore (or is
> there?): You can write now (and at least *execute* much more efficiently)
>
> obj?.store?.book?.filter((book) => book.price < 10)
> .map((book) => book.title) || []
>
> instead of
>
> jsonPath(obj, '$.store.book[?(@.price < 10)].title')
>
> Which reminds me of LINQ which solves similar problems.
I think a descendent operator/method is the primary missing feature.
obj.descendants('book')
obj..book
> > At least Slice Notation has a change of succeeding:
> >
> > <https://github.com/tc39/proposal-slice-notation>
> Yes, I think that would be a useful and unproblematic addition.
>
> I would even like a[-1] as in Python
Doesn't work in bracket notation but at least it works with slice:
```
let xs = ['a', 'b', 'c']
xs.slice(-1) // 'c'
```
I guess you could use proxy to support the bracket form.
This was a little challenging but seems to work:
```
function adapt(Base) {
const handler = {
get(target, prop) {
if (!isNaN(prop)) {
prop = parseInt(prop, 10);
if (prop < 0) {
prop += target.length;
}
}
return target[prop];
}
}
return class extends Base {
constructor(...args) {
return new Proxy(super(...args), handler);
}
};
}
class List extends adapt(Array) {}
let xs = new List('a','b','c')
xs[-2] // "b"
```
> (seriously, is there a use-case for
> properties named named “-1” in an *array*?).
I'm too lazy to check but this reminded me that there was a bug/feature
in an earlier version of Firefox that had '-1' and '-2' defined on the arguments object.
The values of those positions were information like argument length and something else
I forget.
> I added support for using
> negative indexes to access elements from the end of an array in
> JSX:array.js:BigArray with Proxy, and BigArray.prototype.get() to do it
> in a backwards-compatible way, about 5 years ago:
>
> <https://github.com/PointedEars/JSX/blob/e6eb05cb945df7b7304d572ccbac90ae9a632286/array.js#L491-L1158>
Any interest in modernizing to post ES6+?
[toc] | [prev] | [next] | [standalone]
| From | "Michael Haufe (TNO)" <tno@thenewobjective.com> |
|---|---|
| Date | 2021-02-02 19:26 -0800 |
| Message-ID | <f275f2c8-8d54-4df3-875c-01de563146aan@googlegroups.com> |
| In reply to | #39425 |
On Tuesday, February 2, 2021 at 9:19:18 PM UTC-6, Michael Haufe (TNO) wrote: > I guess you could use proxy to support the bracket form. > > This was a little challenging but seems to work: > > [...] > Of course Google Groups broke the indenting... Here is a gist of the same: <https://gist.github.com/mlhaufe/e742bc99954dd3282bee6ba54a6d439c> One would think I'd stop being a masochist with this terrible interface.
[toc] | [prev] | [next] | [standalone]
| From | Thomas 'PointedEars' Lahn <PointedEars@web.de> |
|---|---|
| Date | 2021-02-03 19:42 +0100 |
| Message-ID | <2637940.BEx9A2HvPv@PointedEars.de> |
| In reply to | #39425 |
Michael Haufe (TNO) wrote:
> […] Thomas 'PointedEars' Lahn wrote:
>> Michael Haufe (TNO) wrote:
>> > I wonder if a variant of JSONPath could be promoted into the language
>> > proper.
>> Yes, I am not particularly fond of Stefan Goessners syntax choices
>> either. While I could perhaps live with “@” instead of “.”, coming from
>> the command shell I find “..” to access *subordered* items very
>> counter-intuitive (I also did with E4X). Why did he not propose and
>> implement the familiar XPath syntax? For example, I see no good reason to
>> propose ”$” instead of “/”.
>
> I don't think either could be used:
>
> '$' is a variable name already so that could not become a reserved work
ISTM that he defined “$” to only signify the root element if it occurred as
first character in the path.
> '/' could be used as a prefix operator but with the existence of
> multi-line comments: '/* ... */'
> single line comments: '// ...'
> and '/' as an infix division I think that would be hard to sell.
We are talking about literals here.
> Additionally, if '/' is used as the root, it seems to want '//' as the
> descendant selector like xpath. This would conflict with single line
> comments.
See above.
> Maybe '#' as root?
That’s even worse than “@” :-D “@” I can at least associate with “here”.
>> One problem I see is that there is not really a need for it anymore (or
>> is there?): You can write now (and at least *execute* much more
>> efficiently)
>>
>> obj?.store?.book?.filter((book) => book.price < 10)
>> .map((book) => book.title) || []
>>
>> instead of
>>
>> jsonPath(obj, '$.store.book[?(@.price < 10)].title')
>>
>> Which reminds me of LINQ which solves similar problems.
>
> I think a descendent operator/method is the primary missing feature.
>
> obj.descendants('book')
> obj..book
AISB, I find “..” counter-intuitive.
>> > At least Slice Notation has a change of succeeding:
>> >
>> > <https://github.com/tc39/proposal-slice-notation>
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>> Yes, I think that would be a useful and unproblematic addition.
>>
>> I would even like a[-1] as in Python
^^^^^^^^^^^^^^^^^
> Doesn't work in bracket notation but at least it works with slice:
*facepalm*
> ```
> let xs = ['a', 'b', 'c']
> xs.slice(-1) // 'c'
> ```
>
> I guess you could use proxy to support the bracket form. […]
That is what I did and said. Just not with classes. See below :-D
>> (seriously, is there a use-case for
>> properties named named “-1” in an *array*?).
>
> I'm too lazy to check but this reminded me that there was a bug/feature
> in an earlier version of Firefox that had '-1' and '-2' defined on the
> arguments object. The values of those positions were information like
> argument length and something else I forget.
OK, but that is not an *array*. And a broken implementation (now likely
fixed) is not a good argument against the syntax.
>> I added support for using
>> negative indexes to access elements from the end of an array in
>> JSX:array.js:BigArray with Proxy, and BigArray.prototype.get() to do it
^^^^^^^^^^
>> in a backwards-compatible way, about 5 years ago:
>>
>>
<https://github.com/PointedEars/JSX/blob/e6eb05cb945df7b7304d572ccbac90ae9a632286/array.js#L491-L1158>
>
> Any interest in modernizing to post ES6+?
Yes.
--
PointedEars
FAQ: <http://PointedEars.de/faq> | <http://PointedEars.de/es-matrix>
<https://github.com/PointedEars> | <http://PointedEars.de/wsvn/>
Twitter: @PointedEars2 | Please do not cc me./Bitte keine Kopien per E-Mail.
[toc] | [prev] | [standalone]
Back to top | Article view | comp.lang.javascript
csiph-web