Trouble with "dictionary" creation in JavaScript - javascript

OK, first-off let me tell you that I'm too far from being considered experienced in JavaScript... (perhaps I'm even trying to implement something not actually supported by the language?).
So... here we are...
I want to create a structure like this (it's just an illustrative example) :
Addresses
--- John
--- Phone
--- Address
--- Peter
--- Phone
--- Address
So, I've seen (or perhaps I'm just guessing) that I can do something like that (I've run all my tests in Chrome's JavaScript console) :
var addresses = [];
addresses["John"] = {};
addresses["John"].Phone = "12312312312";
// And so on...
However :
If I do addresses['123'] = {}; then a proper 124-entry array is constructed.
If I do addresses['somestring'] = {}; then addresses remains an empty array [].
What am I doing wrong? Is there no native support for proper dictionaries (or map - no matter how this thing is called) in JavaScript?
Please note: I want to be able to progressively add entries to addresses, as well as keys to each address entry (and not just create it in one-shot).

You are creating an array, but then you are using it as an object instead (which is possible because an array happens to be an object). To contain properties rather than numbered indices, you should use an object:
var addresses = {};
addresses["Holmes"] = { Phone: "14", Address: "Baker street 221b" };

JavaScript has Objects and Arrays.
Arrays are a type of Object that treats properties with numerical with special significance. It will have a length property based on the highest value property name (that is a number), and it has methods such as push, pop and forEach to manipulate its numerical members based on their number.
If I do addresses['123'] = {}; then a proper 124-entry array is constructed.
You already have an array. That just adds a member called 123 to it and updates its length.
If I do addresses['somestring'] = {};
This will add that member to the array, but it won't appear in any of the regular means of accessing array members. You have to access it by name.
Don't give named properties to arrays. Use a plain object.
Is there no native support for proper dictionaries
An object is as close as you can get.
If you want something ordered use an array with numerical properties.
If you want something with named keys, use an object.

When you do this addresses['somestring'] = {}; you wil get an empty array because {} you are assigning an empty object.
Rather if you do addresses["dd"] = {s: "s"} the addresses will have the object

Javascript does not have dictionaries or maps or associative arrays.
It does, however, have objects which can be quite similar. (They can also be quite different, so that is essential to know.)
To make things more confusing, an array is an object. You can put random properties on an array and it will work -- like an object.
Javascript arrays take integer[*] indexes and adjust the .length property.
Objects take string property names. This is important: If you use something that is not a string, it will be converted into one .. usually called [Object object]
Might want to read this:
http://eloquentjavascript.net/chapter4.html
[*] Yea, yea, yea -- they are really strings behind the scenes. It is easier to think of them as integers and avoid that grief.

Related

Is it impossible to use the item() method for getting of array item?

I learn JavaScript through the "JavaScript & jQuery" book by John Duckett (Russian translate).
Author writes two code examples of array item getting:
var colors = ["white", "black","custom"];
var el = document.getElementById('colors');
el.textContent = colors[0];
and
var colors = new Array("white", "black","custom");
var el = document.getElementById('colors');
el.innerHTML = colors.item(0);
In the article he wrotes that for getting of array item can be used item() method. But in the code sources he uses colors[0] instead of colors.item(0) in the second variant.
I see that colors.item(0) doesn't work. Is it wrong info?
JavaScript arrays are specialised objects, which have a particular behaviour and a particular set of methods. .item() is not one of them.
There are many other JavaScript objects which also contain a collection of values. Some of these objects include an .item() method.
The thing is, even though these objects may have some similarity with arrays in that they contain a collection of values, they’re not the same. Arrays, have some features, and these other objects have some others.
To learn more about what JavaScript arrays do have, you can look at: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array
In principal, it would be possible to add an .item() method to arrays by adding to the Array prototype. However, it is certainly not a natural part of JavaScript arrays.
Edit
One of the important properties of the array is in how it is accessed: you can read, replace or create an item using the square brackets ([]). Non-array collections don’t have this feature, so the items need to be accessed with a dedicated method.
Another important property is that the .length property is automatically updated.
Yes, it looks like a mistake in the book. The Array class doesn't have an item method. colors[i] should be used to get an element at a specified index.

Why use an ES6 Map instead of a plain javascript object?

If we can make key/value pairs with plain javascript objects, then what is the reason to use the new ES6 Map object?
When should I use one and when the other? Is Map limited to values or can it contain functions as well?
Anything can be used as a key in a map.
Maps are ordered, and that allows for iteration.
Combining 1 and 2, when you iterate over a map, you'll get a useful array of key-value pairs!
Check out the map.prototype.forEach() documentation.
Source: Another good question/answer exchange. Worth marking this one as a duplicate.
Update:
Adding to this answer to address the question directly:
You should use a map whenever you need to associate things together or preserve insertion order (common data structures need this).
You can use an object when you don't need to do this, but they just do different things.
Update 2:
OP asked if functions are okay too. Yes, because values can be functions too! Check it out:
let x = new Map();
let y = () => {
console.log('derp');
}
x.set(y, "HI");
console.log(x.get(y)); // will log "HI"
For more info, check out the source of this quote, in a great chapter of Eloquent JavaScript:
"Every value has a type that determines its role. There are six basic types of values in JavaScript: numbers, strings, Booleans, objects, functions, and undefined values."
Also, the main differences between Map and Object, from MDN, under the header "Objects and Maps Compared":
An Object has a prototype, so there are default keys in the map. However, this can be bypassed using map = Object.create(null).
The keys of an Object are Strings, where they can be any value for a Map.
You can get the size of a Map easily while you have to manually keep track of size for an Object.
Again, the keys can be any value!
Maps are ordered.
Map keys do not have to be strings

how does javascript move to a specific index in an array?

This is more a general question about the inner workings of the language. I was wondering how javascript gets the value of an index. For example when you write array[index] does it loop through the array till it finds it? or by some other means? the reason I ask is because I have written some code where I am looping through arrays to match values and find points on a grid, I am wondering if performance would be increased by creating and array like array[gridX][gridY] or if it will make a difference. what I am doing now is going through a flat array of objects with gridpoints as properties like this:
var array = [{x:1,y:3}];
then looping through and using those coordinates within the object properties to identify and use the values contained in the object.
my thought is that by implementing a multidimensional grid it would access them more directly as can specify a gridpoint by saying array[1][3] instead of looping through and doing:
for ( var a = 0; a < array.length; a += 1 ){
if( array[a].x === 1 && array[a].y === 3 ){
return array[a];
}
}
or something of the like.
any insight would be appreciated, thanks!
For example when you write array[index] does it loop through the array till it finds it? or by some other means?
This is implementation defined. Javascript can have both numeric and string keys and the very first Javascript implementations did do this slow looping to access things.
However, nowadays most browsers are more efficient and store arrays in two parts, a packed array for numeric indexes and a hash table for the rest. This means that accessing a numeric index (for dense arrays without holes) is O(1) and accessing string keys and sparse arrays is done via hash tables.
I am wondering if performance would be increased by creating and array like array[gridX][gridY] or if it will make a difference. what I am doing now is going through a flat array of objects with gridpoints as properties like this array[{x:1,y:3}]
Go with the 2 dimension array. Its a much simpler solution and is most likely going to be efficient enough for you.
Another reason to do this is that when you use an object as an array index what actually happens is that the object is converted to a string and then that string is used as a hash table key. So array[{x:1,y:3}] is actually array["[object Object]"]. If you really wanted, you could override the toString method so not all grid points serialize to the same value, but I don't think its worth the trouble.
Whether it's an array or an object, the underlying structure in any modern javascript engine is a hashtable. Need to prove it? Allocate an array of 1000000000 elements and notice the speed and lack of memory growth. Javascript arrays are a special case of Object that provides a length method and restricts the keys to integers, but it's sparse.
So, you are really chaining hashtables together. When you nest tables, as in a[x][y], you creating multiple hashtables, and it will require multiple visits to resolve an object.
But which is faster? Here is a jsperf testing the speed of allocation and access, respectively:
http://jsperf.com/hash-tables-2d-versus-1d
http://jsperf.com/hash-tables-2d-versus-1d/2
On my machines, the nested approach is faster.
Intuition is no match for the profiler.
Update: It was pointed out that in some limited instances, arrays really are arrays underneath. But since arrays are specialized objects, you'll find that in these same instances, objects are implemented as arrays as well (i.e., {0:'hello', 1:'world'} is internally implemented as an array. But this shouldn't frighten you from using arrays with trillions of elements, because that special case will be discarded once it no longer makes sense.
To answer your initial question, in JavaScript, arrays are nothing more than a specialized type of object. If you set up an new Array like this:
var someArray = new Array(1, 2, 3);
You end up with an Array object with a structure that looks more-or-less, like this (Note: this is strictly in regards to the data that it is storing . . . there is a LOT more to an Array object):
someArray = {
0: 1,
1: 2,
2: 3
}
What the Array object does add to the equation, though, is built in operations that allow you to interact with it in the [1, 2, 3] concept that you are used to. push() for example, will use the array's length property to figure out where the next value should be added, creates the value in that position, and increments the length property.
However (getting back to the original question), there is nothing in the array structure that is any different when it comes to accessing the values that it stores than any other property. There is no inherent looping or anything like that . . . accessing someArray[0] is essentially the same as accessing someArray.length.
In fact, the only reason that you have to access standard array values using the someArray[N] format is that, the stored array values are number-indexed, and you cannot directly access object properties that begin with a number using the "dot" technique (i.e., someArray.0 is invalid, someArray[0] is not).
Now, admittedly, that is a pretty simplistic view of the Array object in JavaScript, but, for the purposes of your question, it should be enough. If you want to know more about the inner workings, there is TONS of information to be found here: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array
single dimension hash table with direct access:
var array = {
x1y3: 999,
x10y100: 0
};
function getValue(x, y) {
return array['x' + x + 'y' + y];
}

Javascript hash table vs associative arrays

I'm new to javascript and I cannot find answer about some issues, one is the following:
Why in js would be useful an hash table data structure when we can use objects as associative arrays that is simple to use and have a very good performance?
why in js would be useful an hash table data structure when we can use
objects as associative arrays that is simple to use and have a very
good performance?
The only reason I can imaging to implement an hash table data structure is if you want to preserve the ordering of the elements. The for…in loop for objects doesn't guarantee to you in which order the properties ("keys") are returned, even if commonly you can obtain them in chronological order (last added, last returned). But it's not guarantee. For instance, old version of Opera returned the properties in an apparently random order. So, if you need an "ordered" hash table, you need to implement it by yourself.
A javascript hashtable and javascript associative array (and javascript objects) are all the same thing in the underline implementation. These are just different syntax.
So :
var a = {};
a.id = "aa";
is same as:
var a = new Object();
a.id = "aa";
Which is is same as:
var a = {};
a["id"] = "aa";
Associative arrays and hashtables are the same.
These expressions usually means the same too: dictionary, associative array, hashmap, map, hashtable and... the list goes on.
There is a difference between simple ARRAY and HASHTABLE though.
If you want to search an item in an array, the more items you have inside it, the longer will the search takes.
For example searching an item in an array with 10000 elements could takes 100 times longer than in an array with 100 elements.
With hashtables, no matter how many elements you have, the performance remains the same. (Be it 100 elements or even 99999999 elements...)

Remove element from nested object

I have following object:
{"2":{"cid":"2","uid":"2"},"1":{"cid":"1","uid":"3"}}
In this example I want to remove
"1":{"cid":"1","uid":"3"}
from it.
I have tried all solutions that I found on Stack Overflow, and could not make any of them work. I am mostly PHP person, so I might miss something important here?
Just use delete with the appropriate property.
var obj = {"2":{"cid":"2","uid":"2"},"1":{"cid":"1","uid":"3"}};
delete obj["1"];
Note the " around the 1 to mark it as an identifier and not as an array index!
EDIT
As pointed out in the comment, obj is an object and no array no matter how you address the [1] property. My last note was just to make it clear that you are working with an object and not an array.
In my experience most people associate integer properties with arrays and string properties with objects. So I thought it might be more helpful to highlight the property in the way given.
var myObj= {"2":{"cid":"2","uid":"2"},"1":{"cid":"1","uid":"3"}}
delete myObj['1'];
alert ( myObj['1']);
please notice there are Cross platform problems with delete :
Cross-browser issues
Although ECMAScript makes iteration order of objects
implementation-dependent, it may appear that all major browsers
support an iteration order based on the earliest added property coming
first (at least for properties not on the prototype). However, in the
case of Internet Explorer, when one uses delete on a property, some
confusing behavior results, preventing other browsers from using
simple objects like object literals as ordered associative arrays. In
Explorer, while the property value is indeed set to undefined, if one
later adds back a property with the same name, the property will be
iterated in its old position--not at the end of the iteration sequence
as one might expect after having deleted the property and then added
it back.
var arr=[[10,20,30],[40,50,60],[70,80,90]];
for(var i=0;i<arr.length;i++){
for(var j=0;j<arr[i].length;j++){
if(arr[i][j]==50){
arr[i].splice(j,1);
}
}
}
document.write(arr);
JavaScript doesn't have multi dimensional Arrays, only arrays and objects. That said: delete theObject['1']; should work just fine
You could use delete in javascript
Ex:
var x = {"2":{"cid":"2","uid":"2"},"1":{"cid":"1","uid":"3"}};
delete x['1'];
Also, check this:
Deleting Objects in JavaScript
Assign your Object (not an Array) to a variable, this way:
var o = {"2":{"cid":"2","uid":"2"},"1":{"cid":"1","uid":"3"}};
Then do:
delete o['1'];
That's it!

Categories

Resources