What's an Associative Array? - javascript

I'm trying to understand what an associative array really is and what steps are needed to acquire one. I have seen many explanations that are totally different.
I have tried testing it out on my own but can't seem to really get it in the end.
var array = ["one", "two", "three"];
var test = array["one"];
console.log(test);
I expected for it to target the index in which the string "one" is in, but an error occurs.

You are likely looking for a JavaScript Object, what is basically the same as an associative array, dictionary, or map in other languages: It maps strings to values. Unlike Arrays, which use square brackets [] for declaration, Objects use curly braces {} (please note that there are some exceptions).
Try to think of an Object as an associative array:
const arr = {one: 1, two: 2, three: 3};
console.log(arr['one']);
console.log(arr.one);
It is worth noting that Array's in JavaScript are technically objects.
The JavaScript Array object is a global object that is used in the construction of arrays; which are high-level, list-like objects.
The main difference between Array's and Object's is that Arrays are numerically indexed.
const arr = ['fooValue', 'barValue'];
const obj = {foo: 'fooValue', bar: 'barValue'};
console.log('arr: ', arr[0], arr[1]);
console.log('obj: ', obj.foo, obj.bar);
It is worth noting, that unlike primitive types in JavaScript, Object's (and Array's, which are also Object's) are passed by reference, so extra care is needed when attempting to copy the object.
function test(obj) {
obj['oops'] = 'this will modify the object';
}
const obj = {one: 1, two: 2, three: 3};
test(obj);
console.log(obj); // Object was updated
To avoid accidentally mutating your object, you will have to create a new instance of the object before performing operations on it. There are multiple ways to accomplish this:
Destructuring/spreading you object let obj2 = {...obj};
Using Object.assign()

I'm trying to understand what an associative array really is...
JavaScript doesn't have associative arrays in the sense that, for instance, PHP does. JavaScript has:
Arrays, which are (effectively) numerically indexed (see my blog post for why I said "effectively")
Objects, which are collections of properties that have names, which are either strings or Symbols (and which have other features, like inheritance)
Maps, which are collections of key/value pairs where the keys can be any type (not just strings or Symbols)
Arrays
To find the index of an entry in an array, typically you use indexOf (for an === match) or findIndex if you want to provide a predicate function.
var array = ["one", "two", "three"];
console.log(array.indexOf("one")); // 0
Objects
If you wanted, you could create an object that mapped strings to numbers:
var obj = {"one": 1, "two": 2, "forty-two": 42};
console.log(obj["forty-two"]); // 42
Maps
Similarly, a Map could do that:
var map = new Map([
["one", 1],
["two", 2],
["forty-two", 42]
]);
console.log(map.get("forty-two")); // 42

Associative arrays are used to associate something throughout an array.
You can use this with the query string for example:
In order to attain the information from a forum submitted, you need to put the user data into an associative array.
You would start by getting the query string as follows:
var queryString = window.location.search;
queryString = queryString.substring(1);
The reason why I did substring(1) is so we could remove the '?' at the beginning.
Once you have the query string of the website, you'd need a loop to separate the values of data received:
while (queryString.indexOf("+") != -1)
queryString = queryString("+", " ");
This will replace all the '+' signs in the string to spaces, making you get the values without the '+' signs. You'll have "Name=John" for example.
Now we need to split the '&'s from the string.
We also need to make an array ready for the data from the user.
var array = queryString.split("&");
var userData = [];
Afterwards, make a for loop in order to target however amount of data submitted and to attain it individually while storing it into the array:
for (let x = 0; x < array.length; x++)
{
var equalSign = array[x].search("=");
var theKeyValue = array[x].substring(0, equal);
var userDataValue = array[x];
userDataValue = decodeURIComponent(userDataValue); //Puts symbols back
userData[theKeyValue] = userDataValue;
}
This is just an example to follow up with the usage of associative arrays, hopefully this helps. :)

See Wikipedia.
It is a data structure when you can look up a value by a key. This is typically implemented in JS using a Map or an Object.
const data = new Map([
['foo', 'one'],
['bar', 'two']
]);
console.log( data.get("bar") );
I expected for it to target the index in which the string "one" is in, but an error occurs.
You are attempting to look up the index of a property in an array by its value.
That has nothing to do with associative arrays and is achieved with the indexOf method.
var array = ["one", "two", "three"];
var test = array.indexOf("one");
console.log(test);

An associative array, is essentially a hashmap, or an array that associates relationships.
For example if I was to build an associative array for fruits let's say to prices it would look like.
const arr = {'apple': 1, 'orange': 2, 'pear': 3};
console.log(Object.keys(arr));
console.log(Object.values(arr));

Unlike other languages, array in Javascript are not limited by having only numeric indices. They can act as hashes as well (i.e. having a string as a key). An associative array is one where you set the key to be a non-numeric value.
By default, and in the example you provided, ascending numeric values are assigned to each member of the array. I.e.
var array = ["one", "two", "three"];
is equivalent to
var array = [];
array[0] = 'one';
array[1] = 'two';
array[2] = 'three';
An associative array would be one where instead of numeric values you assign a different value:
var array = [];
array['one'] = 'one';
array['two'] = 'two';
However this brings a few caveats in itself and it considered bad practice and the arrays become harder to manage. In cases like there it would be better to use either an object or a Map.

An associative array is a data structure, a data collection, which has the scope of associate a list of key to respective values (key: value).
You can read in Wikipedia here, that are example of associative array for example: Map, Dictionary, etc.
Sample of associative array are also PHP indexed array, e.g.:
$cars[0] = "Volvo";
$cars[1] = "BMW";
$cars[2] = "Toyota";

That's not an associative array, that's just a regular array, filled with text.
An associative array example (you can also use object syntax like Miroslav's answer):
var stuff = [];
stuff['one'] = "hello 1";
stuff['two'] = "hello 2";

Related

Forcing string representation of an array key

I am trying to maintain the order of an array with mixed key types. The array contains mostly keys represented by string values -- but if you enter a numbered key it goes to the front. How can I force a key which is a number to be a string type?
E.g.
array = [];
array["one"] = "some data";
array["two"] = "some more data";
array["3"] = "this should not be the first element";
How can I make "3" a string type to prevent it from moving to the top of the index?
Oh wow did you ever open multiple cans of worms.
Javascript arrays are a special type of Javascript objects, and like all Javascript objects they can have arbitrary string properties:
const foo = [];
foo["bar"] = "hi";
However that string is a property of the array object, not an item in the array:
foo.forEach(console.log); // logs nothing
You can still access it like any other object property:
console.log(foo["bar"]); // "hi"
But it won't show up in the usual iterative constructs like c-style for loops or the map/forEach array methods.
The line in your example
array["3"] = "this should not be the first element";
is very different however, because of Javascript's playing fast and loose with type conversions this actually sets the string to the 4th slot in the array:
const bar = [];
bar["3"] = "oops!"; // equivalent to bar[3] = "oops!"
console.log(bar); // [empty x 3, "oops!"]
This piece of it is actually a good thing (other than the implicit conversion part) rather than a problem: sometimes you need a sparse array and JS supports those. Iterating it will only produce the one element:
bar.forEach((item, index) => console.log(item, index)); // ["oops", 3]
Note though that the string has the correct index of 3, and can be accessed that way even though there's nothing "in front" of it:
bar[3]; // "oops"
So the first two assignments in your example create properties on the array object, and the third assignment is the only one that actually adds an item to the array, at the 4th index (there's nothing at the first 3).
What you seem to want as Reese Casey suggests, is a plain object:
const foo = {}; // curly
foo["some string"] = "whatever";
However now the properties are basically unordered. If you want them to be in a guaranteed specific order you do want an array, but all your indicies will need to be integers, and should be sequential. You can achieve this easily by using the .push method:
foo = [];
foo.push("something");
foo.push("something else");
Now foo will have two elements, in the correct order, and index 0 and 1 respectively.
Update based on comment on the other answer:
I want some of the data to be ordered, and the rest of the data to follow
This can be accomplished through object destructuring:
const responseFromDB = {
oneKeyICareAbout: 3,
anotherKeyICareAbout: 2,
foo: 6,
bar: 7,
};
const {
oneKeyICareAbout,
anotherKeyICareAbout,
*rest,
} = responseFromDB;
const stuffToDisplay = [
oneKeyICareAbout,
anotherKeyICareAbout,
...Object.values(rest),
]; // [3, 2, 6, 7]
And at least the destructured stuff you put in the array will be ordered because by doing so you've ordered it.
Javascript arrays cannot have string indexes. This is actually working incorrectly as the index is adding a property to the array object.
Changing to an object makes more sense for this.
EDIT: Whilst below its mentioned you can have string indexes you are not actually using the array by doing so. The answer by Jared Smith goes into much more detail as to why.
The other answers explain what is happening with your array-object mixture. For having an indexable thing which can reproduce the original order, you can use a Map:
The Map object holds key-value pairs and remembers the original insertion order of the keys.
array = new Map();
array.set("one","some data");
array.set("two","some more data");
array.set("3","this should not be the first element");
console.log("Test of get:",array.get("two"));
console.log("Test of order:");
for(let entry of array)
console.log(entry);

What is the difference between using a string or a number to index an array in Javascript? [duplicate]

This question already has answers here:
Is a JavaScript array index a string or an integer?
(5 answers)
Closed 4 years ago.
In Javascript it is possible to use a number (integer) or a string (or a char) to index an array for example:
array[0] = true;
or
array['0'] = true;
Does the computer memory work different depending on how you index the array or is it the exact same thing to do it both ways?
The indexes are stored internally as strings.
But it's more common practise to use numbers to access an array by it's index.
A property name P (in the form of a String value) is an array index if
and only if ToString(ToUint32(P)) is equal to P and ToUint32(P) is not
equal to 2^³²−1
It's explained in this old post
Below is a snippet that showcases it.
Accessing the index with a string works fine as long that index string only contains digits.
But by expressing the index as a word then it can only be accessed with that word. And console logging the array doesn't show it.
let arr = [0,'a one','a two','a three'];
arr['four'] = 'a four';
arr.push('5');
arr.push(6);
arr.push([7,'7']);
arr.push({a:8, b:'8'});
console.log('\nLog the array:\n\n');
console.log(arr);
console.log('\nAccessing the array:\n\n');
console.log("arr[0]:\t" + arr[0]);
console.log("arr[\'1\']:\t" + arr['1']);
console.log("arr[\'two\']:\t" + arr['two']);
let i=2;
console.log("arr[++i]:\t" + arr[++i]);
console.log("arr[\'four\']:\t" + arr['four']);
console.log('arr[4]:\t'+ arr[4]);
console.log('arr[5]:\t'+ arr[5]);
console.log('\nListing the types in the array:\n\n');
for (var a in arr) console.log(a+'\tindex type: '+ typeof a +', value: '+ arr[a] + ', value type: '+ typeof arr[a]);
And here's a snippet to compare speed between using a number or a string in your browser. It should take roughly the same time.
let arr1 = [];
console.time('Access array through string');
for(let i = 0; i <= 42000000;i++){
arr1['42000000'] = 42;
}
console.timeEnd('Access array through string');
let arr2 = [];
console.time('Access array through integer');
for(let i = 0; i <= 42000000;i++){
arr2[42000000] = 42;
}
console.timeEnd('Access array through integer');
The answer is simple: there is no difference.
Javascript arrays are objects. All keys of objects are strings (or symbols), but never numbers.
Property names must be strings. This means that non-string objects
cannot be used as keys in the object. Any non-string object, including
a number, is typecasted into a string via the toString method. ...see more here
The property accessor [] converts to string first before looking for the property. (some engines may optimize this step and not perform a proper toString call, but it's of no concern here)
So array[0] is interpreted as array['0'].
const a = {
toString: function () {
console.log("a.toString called")
return "1";
}
};
const array = ['a','b','c'];
console.log(array[a]);
When you use quotations for indexing, you're creating a key-value pair in the array. I recommended you stick to numerical notation unless you're intentionally creating those pairs; while array['0'] technically posts to the position, it's bad practice.
Even though myArr['two'] doesn't seem to want to show up in the snippet output, if you hit F12 and look at the console output, you'll clearly see it displayed.
["String 0", "String 1", two: "String 2"]
let myArr = [];
myArr[0] = "String 0";
myArr['1'] = "String 1";
myArr['two'] = "String 2";
console.log(myArr);
As the mdn docs state, https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array
Arrays are actually just objects that have array-like properties. Keys in JavaScript are strings. So when you see an array, it's actually just a set of key-value pairs, where the keys are index numbers.
Arrays are a special data type. Adding keys that do not correlate to possible indexes are added to an 'object property collection' and are not returned when you use the object.
I think the chrome console does the best job of displaying this:
This array is actually an object with keys of 0 1 2 3, a length property, and a prototype.

Javascript Array Showing Inconsistent Behavior

I am confused regarding javascript arrays and how the indices work in these arrays. The length of the array is always 0 no matter how many key value elements are there in the array. Also we can see that the array has only two elements provided that the key is string. Lets consider scenario 1, i have following code.
arr = [];
arr['home'] = 1234;
arr['cat'] = 12345;
console.log(arr.length);
console.log(arr);
Now consider second scenario, i have an empty array and i assign some number to the 20th index of the array. Then when i output the array, the length shows 21 with all the other locations being 'undefined'.
arr = [];
arr[20] = 20;
console.log(arr.length); // Length shows 20 Size of array increased to 21
Now in the third scenario i will assign both numbered indices and string indices and it shows another strange behavior. The length of the array doesn't count the value with string based index. Even though i have 4 number indices and one string based index. So the length should be 6 but the length shows 5.
arr = [];
arr[4] = 4;
arr['home'] = 'home';
console.log(arr);
Now i have two questions.Firstly, Why is the length function not considering string indexed item? Secondly, Why in the case of numbered indices, does the array size is increased to atleast that number?
You have to understand that JavaScript arrays are objects, with some additional behavior. Just like objects, you can assign properties to them.
If the property's name is a numeric string and there is no higher numeric key, the length property is updated. Non-numeric keys don't affect the length property.
The methods in Array.prototype (filter, slice, ...) only work with the numeric keys of the array.
Javascript doesn't have associative arrays like you see in PHP. It has arrays, which have a numerical index associated with the value, and then it has objects which are mapped key => value.
Javascript Arrays and Javascript Objects
const arr = [1, 2, 3, 4, 5, 6, 7];
console.log(arr.length); // outputs 7
const obj = {}
console.log(obj.length); // undefined
// set the key => value for obj from arr
arr.forEach(a => obj[a] = a);
console.log(obj[0]); // undefined
console.log(obj[1]); // 1
console.log(arr[0]); // 1
console.log(arr[1]); // 2
JS Bin
In the example above, you can see that arr is an array and its values are mapped index => value, while obj is an object and its values are mapped key => value. Objects can function as hash maps/associative arrays, but arrays cannot.
If you were to want to get the number of values in an object/hash map, you can always do...
Object.keys(obj).length
This is because Object.keys(...) returns the keys of an object as an array.
For an accurate answer, I should clarify that arrays are objects, however, they function differently than an object inherently does. Per the docs, arrays are "high-level, list-like objects"

JavaScript assoc array add key value pairs unexpected result

This is probably entirely obvious, but why am I not getting the expected JSON string when adding a key-value pair to this JavaScript array?
Next step: As code reveals, I actually wish to have two data sets in the object.
jsFiddle here - Weird, at the moment it only "works" in Chrome
var myKey = "123", myVal="Car";
var arrSummat = new Array();
$('#mybutt').click(function(){
arrSummat["987"] = "Boat";
//arrSummat[myKey] = myVal;
var test = JSON.stringify(arrSummat);
alert(test);
});
In JavaScript building an associative array* or hash map or object may not be terribly obvious. For one, everything is ultimately an object and so the syntax used with associative arrays is valid on everything that isn't an "associate array" which is probably where the confusion arises. First let's address the issue at hand. You probably wanted to use an object instead of an array:
arrSummat = {};
arrSummat["987"] = "Boat";
console.log(JSON.stringify(arrSummat)); // => {"987":"Boat"}
When running your fiddle (in Chrome) I pretty much get an array with 986 null values and then "Boat" (I may be wrong, I'm not hand counting the nulls in that alert).
Now that you're original question is resolved I'd like to point out two things you may want to start doing differently:
Prefer shorthand syntax for objects and arrays. The two examples are functionally the same but you should prefer the second for most purposes.
var myArr = new Array();
var myObj = new Object();
Is the same as:
var myArr = [];
var myObj = {};
The shorthand can even come with some basic values:
var myArr = [1, 2, 3];
var myObj = {one: "1", two: "2"};
Secondly, never use an Array object as anything other than an array. It is syntactically valid to do so but it will produce unexpected results (as you have seen here).
There is no "associative array" in JavaScript, but Objects are commonly used as a substitute and provide similar functionality.
Revised jsFiddle Link

How to stringify an array in Javascript?

I am running the following piece of code:
var arr = [];
arr["aaa"] = {
"xxx" : 1,
"ttt" : 2
};
arr["bbb"] = {
"xxx" : 5,
"qqq" : 6
};
var tmp = JSON.stringify(arr);
alert(tmp);
But the result is []. How does one stringify an array with string keys and object values?
Use
var arr = {};
Arrays should only be used for numerically indexed data, not arbitrary properties. Of course you are able to do it, because they are, in fact, objects. But it won't work in JSON.
Instead, just use objects.
You can't do that, for two reasons:
The stringify method only consider the data in the array, not properties.
There is no JSON format for an array with properties.
If you want the representation of an array in the JSON, you need to put the data in the actual array, not as properties in the array object.
If you want the properties in the JSON, you need to use a plain object instead of an array.

Categories

Resources