Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > comp.lang.javascript > #31911 > unrolled thread
| Started by | Andrew Poulos <ap_prog@hotmail.com> |
|---|---|
| First post | 2016-12-20 14:43 +1100 |
| Last post | 2016-12-20 18:21 +0000 |
| Articles | 6 — 4 participants |
Back to article view | Back to comp.lang.javascript
Get object from one of its values Andrew Poulos <ap_prog@hotmail.com> - 2016-12-20 14:43 +1100
Re: Get object from one of its values Jake Jarvis <pig_in_shoes@yahoo.com> - 2016-12-20 10:42 +0100
Re: Get object from one of its values Andrew Poulos <ap_prog@hotmail.com> - 2016-12-21 07:25 +1100
Re: Get object from one of its values Thomas 'PointedEars' Lahn <PointedEars@web.de> - 2016-12-20 13:33 +0100
Re: Get object from one of its values Thomas 'PointedEars' Lahn <PointedEars@web.de> - 2016-12-20 23:10 +0100
Re: Get object from one of its values John Harris <niam@jghnorth.org.uk.invalid> - 2016-12-20 18:21 +0000
| From | Andrew Poulos <ap_prog@hotmail.com> |
|---|---|
| Date | 2016-12-20 14:43 +1100 |
| Subject | Get object from one of its values |
| Message-ID | <W9ednbBeYoFENcXFnZ2dnUU7-RfNnZ2d@westnet.com.au> |
If there are one or more objects each of which has a property called
childArray whose value is always a one dimensional array and elements of
the array are unique (ie an element cannot also occur in the childArray
of another object) then if I know the value of one element of a
childArray how do I find the object it's associated with?
For example if I have:
var a = {};
a.childArray = [1,2,3,a,b,c,..];
var b = {};
b.childArray = [4,5,6,d,e,f,...];
var c = {};
c.childArray = [7,8,9,g,h,i,...];
...
and I'm given the value "5" how do I find that it's associated with "b"?
The code is dynamically created so I don't know beforehand what or how
many objects will be created.
Andrew Poulos
[toc] | [next] | [standalone]
| From | Jake Jarvis <pig_in_shoes@yahoo.com> |
|---|---|
| Date | 2016-12-20 10:42 +0100 |
| Message-ID | <o3auam$vku$1@dont-email.me> |
| In reply to | #31911 |
Am 20.12.2016 um 04:43 schrieb Andrew Poulos:
> If there are one or more objects each of which has a property called
> childArray whose value is always a one dimensional array and elements of
> the array are unique (ie an element cannot also occur in the childArray
> of another object) then if I know the value of one element of a
> childArray how do I find the object it's associated with?
>
You sequentially check all objects - maybe stop once found - and their
respective childArray properties.
e.g. (if conveniently collected in a useful way)
objectsContainer.find(o => o.childArray.indexOf(5) > -1)
> For example if I have:
>
> var a = {};
> a.childArray = [1,2,3,a,b,c,..];
> var b = {};
> b.childArray = [4,5,6,d,e,f,...];
> var c = {};
> c.childArray = [7,8,9,g,h,i,...];
> ...
>
> and I'm given the value "5" how do I find that it's associated with "b"?
>
> The code is dynamically created so I don't know beforehand what or how
> many objects will be created.
>
Are they collected somewhere at least?
or
Are they (assigned to) global variables?
or
Are they (assigned to) local variables?
[toc] | [prev] | [next] | [standalone]
| From | Andrew Poulos <ap_prog@hotmail.com> |
|---|---|
| Date | 2016-12-21 07:25 +1100 |
| Message-ID | <vtGdnQzI04I9DsTFnZ2dnUU7-aXNnZ2d@westnet.com.au> |
| In reply to | #31913 |
On 20/12/2016 8:42 PM, Jake Jarvis wrote:
> Am 20.12.2016 um 04:43 schrieb Andrew Poulos:
>> If there are one or more objects each of which has a property called
>> childArray whose value is always a one dimensional array and elements of
>> the array are unique (ie an element cannot also occur in the childArray
>> of another object) then if I know the value of one element of a
>> childArray how do I find the object it's associated with?
>>
>
> You sequentially check all objects - maybe stop once found - and their
> respective childArray properties.
>
> e.g. (if conveniently collected in a useful way)
> objectsContainer.find(o => o.childArray.indexOf(5) > -1)
>
>> For example if I have:
>>
>> var a = {};
>> a.childArray = [1,2,3,a,b,c,..];
>> var b = {};
>> b.childArray = [4,5,6,d,e,f,...];
>> var c = {};
>> c.childArray = [7,8,9,g,h,i,...];
>> ...
>>
>> and I'm given the value "5" how do I find that it's associated with "b"?
>>
>> The code is dynamically created so I don't know beforehand what or how
>> many objects will be created.
>>
>
> Are they collected somewhere at least?
I thought "no" but when I created an number of test files I discovered
that any object that contains a childArray property has an id that
begins with "og". So it should be straightfoward enough to collect.
> Are they (assigned to) global variables?
Yes
> Are they (assigned to) local variables?
No.
Andrew poulos
[toc] | [prev] | [next] | [standalone]
| From | Thomas 'PointedEars' Lahn <PointedEars@web.de> |
|---|---|
| Date | 2016-12-20 13:33 +0100 |
| Message-ID | <2298053.9Mp67QZiUf@PointedEars.de> |
| In reply to | #31911 |
Andrew Poulos wrote:
> If there are one or more objects each of which has a property called
> childArray whose value is always a one dimensional array and elements of
> the array are unique (ie an element cannot also occur in the childArray
> of another object) then if I know the value of one element of a
> childArray how do I find the object it's associated with?
>
> For example if I have:
>
> var a = {};
> a.childArray = [1,2,3,a,b,c,..];
> var b = {};
> b.childArray = [4,5,6,d,e,f,...];
> var c = {};
> c.childArray = [7,8,9,g,h,i,...];
> ...
>
> and I'm given the value "5" how do I find that it's associated with "b"?
>
> The code is dynamically created so I don't know beforehand what or how
> many objects will be created.
As Jake said correctly, you need to check the objects sequentially (but see
bottom). This means that you need to check the variables or properties
sequentially that hold references to those objects.
If you know the variables or properties, you can create an array of their
values. With ECMAScript 2016 methods and syntax:
var objects = [a, b, c];
objects.find(obj =>
obj.hasOwnProperty("childArray") && obj.childArray.indexOf(5) > -1);
It might also be necessary to check whether obj.childArray holds a reference
to an Array instance, using Array.isArray().
But suppose the less trivial case that there are variables “a” to at most
“z” to refer to objects, and you do not know how many, then you will have to
use a loop that is checking whether the variable exists and its value is an
object reference. For example:
var obj;
for (var i = "a".charCodeAt(0), end = "z".charCodeAt(0);
i <= end; ++i)
{
var name = String.fromCharCode(i);
/*
* NOTE:
* It is not possible to write a function that determines if a
* variable was declared in a specified execution context as
* there is no way to refer to a calling execution context.
* It is only possible to define such a function in the execution
* context that is to be searched. (this != [[Scope]])
*/
try
{
obj = eval(name);
}
catch (e)
{
if (e instanceof ReferenceError) continue;
}
if (typeof obj != "object" || obj == null) continue;
if (!obj.hasOwnProperty("childArray") || obj.childArray.indexOf(5) < 0)
{
obj = null;
}
else
{
break;
}
}
if (typeof obj == "object" && obj != null)
{
/* use obj */
}
This can be written in a slightly shorter way using an array of identifiers:
/* ["a", "b", "c", …, "z"]; a useful pattern to remember */
var identifiers = Array.apply(null, {length: 26}).map(
(() => {
var offset = "a".charCodeAt(0);
return ((e, i) => String.fromCharCode(i + offset));
})()
);
var matchingIdentifier = identifiers.find(name => {
var obj;
try
{
obj = eval(name);
}
catch (e)
{
if (e instanceof ReferenceError) return false;
}
if (typeof obj != "object" || obj == null) return false;
if (!obj.hasOwnProperty("childArray") || obj.childArray.indexOf(5) < 0)
{
return false;
}
return true;
});
if (typeof matchingIdentifier == "string")
{
var obj = eval(matchingIdentifier);
}
With variables, you can only avoid eval() if you declare potentially missing
variables in advance:
var a, b, …, z;
Then you can generate the array containing the values to be searched as
follows:
var objects = [a, b, …, z];
And proceed as if you knew how many variables there are in the original
code.
The caveat here is that you must not use variable names that are already
used by the original code. The only way to be certain that this does not
happen is declaring variables with “let” (ECMAScript 2015+) instead of “var”
within a Block-like statement of your code, and then only the missing ones.
If possible, access properties instead of variables in this situation; then
you can use Object.property.hasOwnProperty(), or simply “"propertyName" in
object” if inheritance is not an issue.
Finally, if you need to do this search several times, and the referred
objects are not changing in-between, it will improve efficiency greatly if
you maintain a map of values to objects instead:
var v2o = new Map();
objects.forEach(obj => obj.childArray.forEach(el => v2o.set(el, obj)));
Determining the object whose “childArray” property refers to an Array
instance that contains the Number value “5” will then be as simple as
var needle = v2o.get(5);
whereas “needle” will either hold a reference to that object, or “undefined”
if there is no matching object in the indexed haystack referred to by “v2o”.
[Note that this way a value will map to a reference to the last searched
object in which it was found. It is also possible to map a value either to
an array of references to matching objects, or to a reference to the first
searched matching object.
Note also that to know the identifier/name of the variable(s) or
property/properties that referred to that object you need to keep an array
(also) of names, not (only) object references. Objects have identity, not
name.]
The Map object is specified as a constructor property of the global object
since ECMAScript 2015 as well (ES 2015, § 18.3.4) A simplified polyfill of
it is easily written:
if (typeof Map != "function")
{
var Map = function () {
/*
* NOTE:
* Assigns reference to object with empty prototype chain,
* to avoid name collisions; a polyfill may be necessary.
*/
this.items = Object.create(null);
};
Map.prototype.get = function (key) {
return this.items[key];
};
Map.prototype.set = function (key, value) {
this.items[key] = value;
};
}
For a more elaborate version, that is however not yet written to be
ECMAScript 2015 compliant as it was based on the Java implementation (e.g.,
.put = .set), see
<https://github.com/PointedEars/JSX/blob/517e2fa56831a3dff8eb2bb7c7e7cbe45c5d0a86/map.js>.
--
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 | Thomas 'PointedEars' Lahn <PointedEars@web.de> |
|---|---|
| Date | 2016-12-20 23:10 +0100 |
| Message-ID | <1771227.kXSN5OTJKJ@PointedEars.de> |
| In reply to | #31918 |
Thomas 'PointedEars' Lahn wrote:
> if (!obj.hasOwnProperty("childArray") || obj.childArray.indexOf(5) < 0)
> {
> return false;
> }
>
> return true;
This can be simplified to
return (obj.hasOwnProperty("childArray")
&& obj.childArray.indexOf(5) > -1);
or
return (obj.childArray && obj.childArray.indexOf(5) > -1);
if it does not matter that the “childArray” property is inherited.
(But it is assumed here that it holds a reference to an Array instance,
and that the Array.prototype.indexOf() method of ES 5+ is implemented.)
--
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 | John Harris <niam@jghnorth.org.uk.invalid> |
|---|---|
| Date | 2016-12-20 18:21 +0000 |
| Message-ID | <citi5chvp0c26shm626me5ui9d8j398nit@4ax.com> |
| In reply to | #31911 |
On Tue, 20 Dec 2016 14:43:21 +1100, Andrew Poulos
<ap_prog@hotmail.com> wrote:
<snip>
>var a = {};
> a.childArray = [1,2,3,a,b,c,..];
>var b = {};
> b.childArray = [4,5,6,d,e,f,...];
>var c = {};
> c.childArray = [7,8,9,g,h,i,...];
>...
>
>and I'm given the value "5" how do I find that it's associated with "b"?
<snip>
One way is for 5 to have a pointer back to b. Replacing 5 by an object
with 5 as one property, value, and b as another, owner, would make
this possible.
But if 5 came from the keyboard then obviously this wouldn't help.
So another way is to record the (child value, owner object) in a Map,
updated whenever an array changes.
John
[toc] | [prev] | [standalone]
Back to top | Article view | comp.lang.javascript
csiph-web