Check if key is defined in associative array

J

JGH

How can I check if a key is defined in an associative array?

var users = new array();
users["joe"] = "Joe Blow";
users["john"] = "John Doe";
users["jane"] = "Jane Doe";

function isUser (userID)
{
if (?????)
{ alert ("This is a valid ID"); }
else
}

But what goes in place of the ????
 
M

Michael Winter

How can I check if a key is defined in an associative array?

Just to dispel any misconceptions, there's no such thing as an associative
array in ECMAScript/Javascript. What you are actually using is a feature
of objects - their ability to have properties added at run-time.
var users = new array();
users["joe"] = "Joe Blow";
users["john"] = "John Doe";
users["jane"] = "Jane Doe";

Using an actual array is a waste. You aren't using it to store values by
ordinal number, you're just using the fact that it's an object.

var users = new Object();

or

var users = {}; // Braces, not parentheses

If the list is static, you could write:

var users = {
joe : 'Jow Blow',
john : 'John Doe',
jane : 'Jane Doe'
};

If an id contains an illegal character, specify the property name as a
string:

'mike-winter' : 'Michael Winter'
function isUser (userID)
{
if (?????)
{ alert ("This is a valid ID"); }
else
}

But what goes in place of the ????

If there is no property that goes by the name contained in userID,
attempting to access that property will yield undefined. You can check for
that by comparing the type:

if('undefined' != typeof user[userId]) {
// valid ID
}

Hope that helps,
Mike
 
A

Alexis Nikichine

Michael said:
function isUser (userID)
{
if (?????)
{ alert ("This is a valid ID"); }
else
}

But what goes in place of the ????


If there is no property that goes by the name contained in userID,
attempting to access that property will yield undefined. You can check
for that by comparing the type:

if('undefined' != typeof user[userId]) {
// valid ID
}

Until the day you notice that isUser( "pop" ) alerts that "pop" is a
valid ID, you'll get on fine with this solution.

Why so ? Because pop, (or push, length, slice...) is a member of Array
objects, and you can accidentally fall on it (and its typeof string is
"function"). The two syntaxes, user.pop and user["pop"], have similar
effects.

I advise you to check type against the expected type of user[userId]:

if( 'string' == typeof user[userId] ) {
// valid ID
}

Using arrays as associative containers has pitfalls; you may wish to
read the misnamed thread "Arrays as hash tables"

http://groups.google.com/[email protected]&rnum=1

Alexis
 
M

Michael Winter

On Thu, 18 Nov 2004 10:09:15 +0100, Alexis Nikichine

[snip]
I advise you to check type against the expected type of user[userId]:

if( 'string' == typeof user[userId] ) {
// valid ID
}

Yes, that is better. I forgot about the existing properties that an object
will have, such as toString and prototype.
Using arrays as associative containers has pitfalls [...]

Indeed. Notice that the first thing that both Lasse and Douglas said was
don't use an array. Use a simple object instead.

[snip]

Mike
 
J

JGH

Michael Winter said:
If an id contains an illegal character, specify the property name as a
string [...]
Hope that helps,

It helped a lot. I got my old code (the stuff you corrected) off a
tutorial on the web. So that's why I was unaware I was doing it wrong.

Anyway, it mostly works now. Problem is the values for user ids and
names come from a database and may contain illegal values. I'm
generating the list of user ids and names via a few lines of visual
basic. But what it ends up with is something like this:


var users = {
~!# : 'Don't use this id',
'ton : 'O'Neal, Ted',
joe : 'Jow Blow',
john : 'John Doe',
jane : 'Jane Doe'
};

There are non-alpha characters in the ID and apostrophe's in the name.
That's why I was using quotes in my original code. Is that wrong?
 
M

Michael Winter

[snip]
There are non-alpha characters in the ID and apostrophe's in the name.
That's why I was using quotes in my original code. Is that wrong?

Either single- or double-quotes are fine. I used single out of habit
rather than neccessity. Just make your VB code place double quotes around
all values so you end up with:

var users = {
"~!#" : "Don't use this id",
"'ton : "O'Neal, Ted",
"joe" : "Jow Blow",
"john" : "John Doe",
"jane" : "Jane Doe"
};

I assume that double quotes can't occur but if, for some reason, you do
need to include a double quote, output it as \":

"\"This value contains quotes\""

Good luck,
Mike
 
L

lawrence

Michael Winter said:
Using an actual array is a waste. You aren't using it to store values by
ordinal number, you're just using the fact that it's an object.

You can loop through the properties of an object the same way you can
loop through an array?


var users = {}; // Braces, not parentheses

That's interesting. What exactly is being said here? Two braces
suggests, to me, a block of scope or a function. But a function would
usually have a name. Is this sort of like creating a fuction called
users and then, at the same time, creating a reference to it?



If the list is static, you could write:

var users = {
joe : 'Jow Blow',
john : 'John Doe',
jane : 'Jane Doe'
};

This looks to be like an array. If it is not, then what is it?
 
S

Steve van Dongen

You can loop through the properties of an object the same way you can
loop through an array?

No, the opposite. You can loop through items in an array the same as
properties of an object.

If you have an array
var a = ["Joe", "John", "Jane"]
you can loop through with the numeric array index
for (var i = 0; i < a.length; i++)
{
echo(a
}
or the property name
for (var i in a)
{
echo(a
}

Using the numeric index is faster because looping through each
property requires allocating memory and initializing strings (the
property names are strings).

However, if you have a very sparse array -- for example, an array with
a length of 1000 but only 5 items in it -- looping by property name is
faster because it iterates over only the 5 actual items whereas
looping numerically iterates over all 1000.
That's interesting. What exactly is being said here?

It's an object with no properties (aside from the properties all
Objects have).
Two braces
suggests, to me, a block of scope or a function. But a function would
usually have a name. Is this sort of like creating a fuction called
users and then, at the same time, creating a reference to it?


This looks to be like an array. If it is not, then what is it?

It's an object. It's the short form of
var users = new Object();
users.joe = "Jow Blow";
users.john = "John Doe";
users["jane"] = "Jane Doe";

http://msdn.microsoft.com/library/en-us/script56/html/js56jsconobjects.asp

Regards,
Steve
 
J

JGH

Steve van Dongen said:
This looks to be like an array. If it is not, then what is it?

It's an object. It's the short form of
var users = new Object();
users.joe = "Jow Blow";
users.john = "John Doe";
users["jane"] = "Jane Doe";


Probably what happens when you create what looks like a hash array in
javascript is that the interpreter passes that to the code to create an
object which in turn creates a hash array. Proof of at least the first
half of that is in the fact that a hash array has the standard
properties of an object.

So you can't actually create a hash array in javascript -- the
interpreter just won't let you. However, every object you create is
probably actually a hash array.

Hence the reason for much of the confusion, IMO. People see something
like this:

var users = {};

All that says is create an "object" which is a pointer to an array of
pointers to strings, integers, functions, other objects, etc.

It never occured to me before but that's one thing that's nice about
perl. That extra layer of abstraction isn't there. Objects are openly
hashrefs.
 
M

Michael Winter

Steve answered most of your questions, so I'll cover the one thing I
notice he didn't address in detail.
[snip]
var users = {}; // Braces, not parentheses

That's interesting. What exactly is being said here? Two braces
suggests, to me, a block of scope or a function. But a function would
usually have a name. Is this sort of like creating a fuction called
users and then, at the same time, creating a reference to it?

As Steve said, it creates an object. To be more specific, it's an object
literal, similar to the other literal types (number, array, regular
expression, and string) in that it assigns an initialised value to an
identifier. In this case, though, the initialisation is just a simple
object like an empty string or array.
This looks to be like an array. If it is not, then what is it?

This is an object literal that contains a list of property names and
values. The property name can be simple like an identifier; essentially
letters, numbers, underscores (_), and Dollar symbols ($).

The property name can also be a number or string literal. In the latter
case, this allows for more complex names that can't be normally be
specified. Note that although a number can be used to name a property, it
doesn't make the object an array. For example:

// Object literal
var obj = {
5 : 'five'
};
obj[5] // 'five'
obj.length // undefined

// Array literal [1]
var obj = [
,,,,, 'five'
];
obj[5] // 'five'
obj.length // 6

Hope that helps,
Mike


[1] Just to explain the series of commas (elisions), they define "empty"
elements. Each elision adds one to the length property of the array, but
it doesn't actually add an array element.
 
L

lawrence

Michael Winter said:
This looks to be like an array. If it is not, then what is it?

This is an object literal that contains a list of property names and
values. The property name can be simple like an identifier; essentially
letters, numbers, underscores (_), and Dollar symbols ($).

The property name can also be a number or string literal. In the latter
case, this allows for more complex names that can't be normally be
specified. Note that although a number can be used to name a property, it
doesn't make the object an array. For example:

// Object literal
var obj = {
5 : 'five'
};
obj[5] // 'five'
obj.length // undefined

// Array literal [1]
var obj = [
,,,,, 'five'
];
obj[5] // 'five'
obj.length // 6

So object doesn't have a length() method. And when you go obj[5] with
an object, its not an index between the brackets, its a property name?
So you can iterate through the properties of an object much as you
would through a hash table?

What are the differences, in Javascript, between an object and a hash
table that has pointers to properties and functions?
 
M

Michael Winter

The footnotes in this post go into more detail. I'd only read them if
you're comfortable with what you know about the subject. You might get
confused otherwise.

[snip]
So object doesn't have a length() method.

You mean length property. :p

Correct, an object doesn't have its own built-in length property.
And when you go obj[5] with an object, its not an index between the
brackets, its a property name?

Exactly.

Between the brackets you place an expression. It can be simple, like a
number or string, or something more complex like a function call or string
concatenation. This is how you can create property names at run-time.

The expression is evaluated and converted to a string[1], and the property
name is accessed.

The difference between arrays and other objects when assigning to a
property, is that it treats numbers as a special case[2]. Numeric indices
can update the length property of an array, but other names do not.
So you can iterate through the properties of an object much as you would
through a hash table?

For the most part, yes, with a for..in statement:

for(var propName in obj) {
/* propName is a string containing the property name.
* You can access the property value with obj[propName]
*/
}

The important part to note is that properties have attributes. You can't
actually modify these attributes, but they do exist.

There are four: ReadOnly, DontEnum, DontDelete, and Internal. The ability
to enumerate object properties with the code above is affected by the
second attribute, DontEnum. If it's present, you can access the property
directly, but the code above will skip it. Many built-in properties have
this attribute set. Properties you have *created* yourself will never have
this attribute set, so they can always be enumerated.
What are the differences, in Javascript, between an object and a hash
table that has pointers to properties and functions?

Depends on what particular implementation you're contemplating.

The biggest difference is that ECMAScript objects always contain certain
properties such as toString. You have to be careful not to confuse these
existing properties with actual keys.

If you're comparing to Java's Hashtable object, another big difference is
that it can use any object type (as long as it implements the hashCode and
equals methods) as a key, whereas property names are always strings in
ECMAScript.

Hope that helps,
Mike


[1] That part is important. Some hash tables allow you to use different
types as keys, which might lead you to believe that:

var obj = new Object();
var arr = new Array();

arr[obj] = ...;

allows you to assign values based on the actual object (I did once).
However, what happens is the object is converted to a string. As most
objects will simply return '[object Object]', or something similar, you
have to be careful here.

Also note that

arr[5] and arr['5']

are the same as the number will be converted to a string.


[2] It performs, what is effectively,

/* Convert name to string.
*
* e.g. arr[10], arr[0xa] and arr['10']
* all become '10'
*/

propertyName = String(propertyName);

/* If name, converted to a number then back to string,
* remains the same, treat as array index. If not, treat
* as property name.
*
* e.g. 1 arr[10], arr[0xa] and arr['10']
* all become '10'. Converted to a number and back
* to a string is still '10', and as '10' == '10',
* they are all treated as array indices.
* e.g. 2 arr['0xa'] to a number and back to a string
* is '10', but '0xa' != '10' so is a property, not
* not an index.
*/

if(String(Number(propertyName)) == propertyName) {

/* If the array index is greater than, or equal to, the
* length of the array, update the length property.
*/

if(Number(propertyName) >= array.length) {
array.length = Number(propertyName) + 1;
}
}
 
G

Grant Wagner

JGH said:
Michael Winter said:
If an id contains an illegal character, specify the property name as a
string [...]
Hope that helps,

Anyway, it mostly works now. Problem is the values for user ids and
names come from a database and may contain illegal values. I'm
generating the list of user ids and names via a few lines of visual
basic. But what it ends up with is something like this:

var users = {
~!# : 'Don't use this id',
'ton : 'O'Neal, Ted',
joe : 'Jow Blow',
john : 'John Doe',
jane : 'Jane Doe'
};

There are non-alpha characters in the ID and apostrophe's in the name.
That's why I was using quotes in my original code. Is that wrong?

No, if you can't be guaranteed that the property is going to contain special
characters or not, it would be wise to always surround it in quotation
marks:

var users = {
'~!#' : 'Don\'t use this id',
'\'ton' : 'O\'Neal, Ted',
'joe' : 'Jow Blow',
'john' : 'John Doe',
'jane' : 'Jane Doe'
};

In addition to escaping single quotation marks, you should consider that the
data from the database may contain new line characters and replace those
with \n or \r.
 
M

Michael Winter

This page says Javascript has associative arrays:

http://www.pageresource.com/jscript/jarray2.htm

A search on Google reveals dozens of such tutorials. Are they all wrong?

They're certainly misleading. For a start, it has nothing to do with
arrays, as I've previously described. Moreover, they are demonstrating a
feature of the language but describing it as something completely
different.

Javascript does not have associative arrays. It just possesses syntax that
can be used in that way. However, a proper hash table requires much more
work.

Mike
 
L

lkrubner

.
They're certainly misleading. For a start, it has nothing to do with
arrays, as I've previously described. Moreover, they are demonstrating
a
feature of the language but describing it as something completely
different.
Javascript has too many friends, and they are not very good as friends.
From what little I've learned in the last 2 months, it seems to me no
other language is so frequently misrepresented by people who know it
well.

I'm thinking of buying a book on Javascript to further my education.
It's a toss up between Danny Goodman's Javascript Bible and the
O'Rielly book. I've heard good things about the O'Rielly book, but I'm
partial to the Goodman book because back in 1995 when I learned
Hypertalk his book on HyperCard was absolutely a blast to read. Any
Javascript books you personally like?
 
J

Joakim Braun

<[email protected]> skrev i meddelandet
Any Javascript books you personally like?

Danny Goodman's "Dynamic HTML" is great. Covers CSS, DOM, Javascript and
more. Not a tutorial really, more of a comprehensive reference books with a
lot of examples thrown in.

Joakim Braun
 
M

Michael Winter

[snip]
From what little I've learned in the last 2 months, it seems to me no
other language is so frequently misrepresented by people who know it
well.

The thing is: most people don't know it that well at all. I didn't until I
began reading this group.

[snip]
Any Javascript books you personally like?

I've never read any. The only pieces of literature I've read are the
Netscape guides and references, the ECMA-262 Standard, various articles
posted here, and those on Richard Cornford's
(<URL:http://www.litotes.demon.co.uk/>) and Douglas Crockford's
(<URL:http://www.crockford.com/>) site.

Mike
 
D

Dr John Stockton

JRS: In article <[email protected]>
, dated Wed, 8 Dec 2004 15:48:10, seen in (e-mail address removed) posted :
This page says Javascript has associative arrays:

http://www.pageresource.com/jscript/jarray2.htm

A search on Google reveals dozens of such tutorials. Are they all wrong?

Please set your system to give proper attributions, such as precede the
quoted material above; or convert to a system that honours accepted
Usenet practice. See sig below. Likewise, please quote some, but not
all, of the previous article; see this newsgroup's Wednesday FAQ.


One cannot reasonably expect consistent or accurate terminology from
arbitrary Web pages. As a general rule, the more pretentious a URL or
site title is, the less reliable the contents are.


And, in response to a different point, a Web browser should be used to
browse the Web, and to fill in simple forms. It should not be used as
an authoring tool, for which use a plain-text editor, word processor, E-
mailer, news-reader, etc.; i.e. well-written, purpose-designed tools.

If you are obliged to enter much text in an unreliable Web-based
service, prepare it independently and copy'n'paste it in.
 
L

lkrubner

Thanks for the tip, Cornford and Crockford's sites are both a bit
amazing. I find myself drowning in technical details, perhaps you could
offer some clarity on them. Reading the article below, (linked to from
Cornford's site) I'm curious if there is ever a time when a Javascript
programmer needs to know anything about the Activation object? Has
there ever been a time when you yourself have needed to use your
knowledge of it in any way? Can I ignore this bit?


=============================

http://www.jibbering.com/faq/faq_notes/closures.html

When an execution context is created a number of things happen in a
defined order. First, in the execution context of a function, an
"Activation" object is created. The activation object is another
specification mechanism. It can be considered as an object because it
ends up having accessible named properties, but it in not a normal
object as it has no prototype (at least not a defined prototype) and it
cannot be directly referenced by javascript code.

The next step in the creation of the execution context for a function
call is the creation of an arguments object, which is an array-like
object with integer indexed members corresponding with the arguments
passed to the function call, in order. It also has length and callee
properties (which are not relevant to this discussion, see the spec for
details). A property of the Activation object is created with the name
"arguments" and a reference to the arguments object is assigned to that
property.

Next the execution context is assigned a scope. A scope consists of a
list (or chain) of objects. Each function object has an internal
[[scope]] property (which we will go into more detail about shortly)
that also consists of a list (or chain) of objects. The scope that is
assigned to the execution context of a function call consists of the
list referred to by the [[scope]] property of the corresponding
function object with the Activation object added at the front of the
chain (or the top of the list).

Then the process of "variable instantiation" takes place using an
object that ECMA 262 refers to as the "Variable" object. However, the
Activation object is used as the Variable object (note this, it is
important: they are the same object). Named properties of the Variable
object are created for each of the function's formal parameters, and if
arguments to the function call correspond with those parameters the
values of those arguments are assigned to the properties (otherwise the
assigned value is undefined). Inner function definitions are used to
create function objects which are assigned to properties of the
Variable object with names that correspond to the function name used in
the function declaration. The last stage of variable instantiation is
to create named properties of the Variable object that correspond with
all the local variables declared within the function.

The properties created on the Variable object that correspond with
declared local variables are initially assigned undefined values during
variable instantiation, the actual initialisation of local variables
does not happen until the evaluation of the corresponding assignment
expressions during the execution of the function body code.

It is the fact that the Activation object, with its arguments property,
and the Variable object, with named properties corresponding with
function local variables, are the same object, that allows the
identifier arguments to be treated as if it was a function local
variable.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,781
Messages
2,569,615
Members
45,297
Latest member
EngineerD

Latest Threads

Top