Javascript Array Key Lookup - javascript

I'm sorry if this has been asked before, it's something that's difficult to search for...
I want to use a javascript Array to hold objects, with the key as the ID
for example, let's say I had a bunch of people who had different IDs
var people = new Array();
var person = {property: value}; // this is person ID 4
var people[4] = person;
I want to be able to then reference that user by saying, people[ID].propery
The problem is that the output of this array now would be;
null,null,null,null,object
Because it's expecting the keys to be 0,1,2,3,4
Am I being stupid or something? :-) We can do it for strings right, so why not non-sequential numbers?
What I'm trying to avoid is having to loop over every single object in the array every time I want to access a particular person inside it, therefore I figured that using the ID number as the key would work
Thanks guys! :-)

Use a dictionary object
var people = {};
people[4] = 'me';

I'd suggest you use collections. A collection is an array of objects. You can then pass properties on each person. You can filter your collection by any property. So close to what you're doing, but instead of relaying on the index, pass the id for each person.
var people = []; // a collection
var person = {
id: 4,
name: 'John'
};
people.push(person);
// Filtering:
// By id
var john = people.filter(function(person) {
return person.id == 4;
});
// By name
var john = people.filter(function(person) {
return person.name == 'John';
});
You can abstract those loops above to re-use them. Also make sure your id's are unique. If data is coming from the DB it should be OK, otherwise I'd keep track of them somewhere.
The advantage of collections, as opposed to a plain object with keys is that you can sort and filter, while an object, where the order of properties is not guaranteed, you can't do it as simple.
Note that filter only works on "modern browsers", so IE9+, but there are polyfills for older browsers.

when we use a string as key, like this:
var people = {}; //this is an object
people[name] = 'toto';
we are adding new property to this object, because each object in javascript can be seen as a hashtable.
If you use an array, it's still an object, you can add properties to it using string as key. But if you do something like people[4] = 'toto';, you are adding a string to the array, the length of the array will then become 5. Of course the number 4 will still be a property of this array object.

Related

Is array better than objects for storing and searching key value pairs in javascript?

I am fetching data from db and storing it in an array in key value pair, so that i can get values of respective keys as below
var test = [];
for () //fetching and storing from db
{
test[key_array[i]] = "value i";
.
.
.
}
test["id_1"] = "value 1"; //to get the value of id_<number>
we can achive this though objects too. I wanted to know which is the better option to consider, if we want a fast and optimized code
Is array better than objects for storing and searching key value pairs in javascript?
No. In fact, you're not using the array as an array, you're using it as an object. You could literally change your
var test = [];
to
var test = {};
// or
var test = Object.create(null); // To avoid it having a prototype
and it would do the same thing you're seeing now:
var test = {};
test["id_1"] = "value_1";
console.log(test["id_1"]);
var test2 = Object.create(null);
test2["id_2"] = "value_2";
console.log(test2["id_2"]);
(And you should change it, since using an array only for its object features is confusing to people maintaining your code.)
[] is a property accessor that accepts the property name as a string. (We use it with standard arrays as well, using numbers, but in theory they get converted to strings before the property is looked up, because standard arrays aren't really arrays at all¹.)
In ES2015+, of course, you'd probably use a Map, not an object:
const test = new Map();
test.set("id_1", "value_1");
console.log(test.get("id_1"));
¹ That's a post on my anemic little blog.
Arrays, are just a kind of object specialized for storing sequences of things. If you evaluate typeof [], it produces "object".
https://eloquentjavascript.net/04_data.html#h_cqg63Sxe3o
The idea of an array is store sequences of data with the same type or logic structure. Thus, is logic put the data come from a db into an array.
Note that you should avoid this because it can become very confusing :
var test = [];
test["id_1"] = "value_1";
test[-1] = "value_0";
console.log(test[-1],test["id_1"]);
console.log(test.length,Array.isArray(test));
It lets you think that test is an array (and it is) but test[-1] and test["id_1"] are not part of the array (that's why Array.isArray(test) returns true, but test.length is still equal to 0. See explanation on link provided by mister T.J. Crowder

An Array of Related Data. Maybe array of ojects

I'm new to javascript but comming along good enough.
i have a project and i need to store alot of related data.
e.g. Full name, DOB, age, height,etc.
my idea after seeing objects was to have an array of object.
that's the idea but i found no good information online that would help me execute this.
basically were my idea came from was structs in C that i treat as records.
so i'd have and array of structs in c and the rest is self explanitory.
but i was to store the related data together like how i'd store data with a struct array.
please keep in mind unknown amount of entries
EDIT:
i found a simpler method that seem to work compare to the complicated things i'm getting as a starter.
var array= [];
function dosomething(){
for(var i=0;i<whateverNumber;i++){
array[i] = {name: "Delano", age:19, so on so forth}
}
}
You can simply create a variable and then start pushing the object into your array something like this
var obj = {id:1,age:26,name:"jhon doe"};
var obj2= {id:2,age:24,name:"jhon doe2"};
var arr = []
arr.push(obj,obj2)
console.log(arr)
and to remove the last object from your array of object simply use arr.pop()

Javascript array index

Sorry for asking a noob question but if I have an array:
MyArray["2cd"]="blah1";
MyArray["3cx"]="blah3";
MyArray["8cz"]="blah2";
And a string myStr="2cd";
And then I use MyArray[myStr] to get the value of blah, how can I get the number I am accessing in the object/array or 0 in this case?
If I may read between the lines, it sounds like you're thinking that the code you posted:
MyArray["2cd"] = "blah1";
MyArray["3cx"] = "blah3";
MyArray["8cz"] = "blah2";
will automatically become the equivalent of:
MyArray[0] = MyArray["2cd"] = "blah1";
MyArray[1] = MyArray["3cx"] = "blah3";
MyArray[2] = MyArray["8cz"] = "blah2";
and therefore you can get the string "blah1" either of these two ways:
var foo = MyArray[0]; // sets foo to "blah1"
var bar = MyArray["2cd"] // also sets bar to "blah1"
But that's not how JavaScript works.
You certainly can set things up so you can use my MyArray[0] and MyArray["2cd"] to fetch the same value, but you have to do it explicitly as in my example.
One thing you didn't mention is how you declared MyArray itself. Is it an Array or an Object? That is, before the code you posted, did you create MyArray with:
var MyArray = {}; // or equivalently, var Array = new Object;
or:
var MyArray = []; // or equivalently, var Array = new Array;
The first example creates an Object, the second an Array.
What is a bit confusing is that JavaScript has both of these two types, which in many cases you can use somewhat interchangeably. But it's customary to use an Object when you are using arbitrary (generally but not necessarily non-numeric) keys into the object, as in your example. Conversely, it's customary to use an Array when you are primarily using strictly numeric indexes.
In fact, JavaScript's Array type inherits from the Object type. An Array is simply an Object with some additional behavior:
An Array has additional methods such as .push() which appends an item to the array.
An Array has a .length property which is automatically updated when you add elements with .push() or a direct array[123] assignment, or when you remove elements with .pop() or other methods.
What JavaScript doesn't have, as Fabrício pointed out, is an "associative array" that behaves like what you might find in some other languages. It has Objects and it has Arrays (which inherit from Objects), and you have to deal with each of those on their own terms.

How to merge these arrays/json objects?

I am a bit confused at this point on what is an object, what is an array, and what is a JSON. Can someone explain the differences in syntax between the two? and how to add items to each, how to merge each type, and such? I am trying to get this function to take the new information from a JSON object (I think) and merge it with some new information. This information will then be passed to a PHP script to be processed.
Here is the console output:
{"public":{"0":["el29t7","3bmGDy"]}}
{"public":"[object Object][object Object]"}
Here is the JS I am using:
/* Helper function to clean up any current data we have stored */
function insertSerializedData(ids, type) {
// Get anything in the current field
current_data = $('#changes').val();
if (!current_data) {
var data = {};
data[index++] = ids;
var final_data = {};
final_data[type] = data;
$('#changes').val(JSON.stringify(final_data));
} else {
current_data = JSON.parse(current_data);
var data = {};
data[index++] = ids;
// Does the index exist?
if (type in current_data) {
var temp_data = current_data[type];
current_data[type] = temp_data + data;
} else {
current_data[type] = data;
}
//var extra_data = {};
//extra_data[type] = data;
//$.merge(current_data, extra_data);
$('#changes').val(JSON.stringify(current_data));
}
console.log($('#changes').val());
}
The idea is if the key (public, or whatever other ones) doesn't exist yet, then to make it point to an array of arrays. If it does exist though, then that of array of arrays need to be merged with a new array. For instance:
If I have
{"public":{"0":["el29t7","3bmGDy"]}}
and I want to merge it with
["aj19vA", "jO71Ba"]
then final result would be:
{"public":{"0":["el29t7","3bmGDy"], "1":["aj19vA", "jO71Ba"]}}
How can i go about doing this? Thanks
Excellent two-part question. Overall, the second question is non-trivial because of the complexity of the first.
Question 1:
what is an object, what is an array, and what is a JSON. Can someone
explain the differences in syntax between the two?
Question 2:
and how to add items to each,
Question 3:
how to merge each type, and such?
Answer 1:
This is a common stumbling point because, JavaScript is more flexible than one might initially expect. Here is the curve.
In JavaScript everything is an object.
So here is the code for each:
//What is an object?
var obj = { };
var obj2 = { member:"value", myFunction:function(){} }
Above is an empty object. Then another object with a variable and a function.
They are called object-literals.
//What is an array
var array1 = [ ] ;
var array2 = [0,1,2,3,4];
Above is an empty array. Then another array with five Integers.
Here is the curve that causes confusion.
//Get elements from each of the prior examples.
var x = obj2["member"];
var y = array2[1];
What??? Both Object and Array are accessing values with a bracket?
This is because both are objects. This turns out to be a nice flexibility for writing advanced code. Arrays are objects.
//What is JSON?
JSON stands for JavaScript Object Notiation. As you might have guessed. Everything is an object... It is also an { }; But it is different because - it is used to transfer data to - and - from JavaScript, not actually used (commonly) in JavaScript. It is a file transfer format.
var JSONObject = {"member":"value"};
The only difference to the prior example is quotes. Essentially we are wrapping the object literal as a string so that it can be transferred to a server, or back, and it can be reinterpreted, very easily. Better than XML - because it does not have to be custom-parsed. Just call, stringify() or ParseJSON(). Google it. The point is... JSON can be converted into an object-literal JS object, and JS object-literals can be converted into JSON, for transfer to a server or a CouchDB database, for example.
Sorry for the tangent.
Answer 2:
How to add an item to each? Here is where the curve stops being a nuisance, and starts being awesome! Because everything is an object, it is all just about the same.
//Add to an object
var obj {member1:"stringvalue"}
obj.member2 = "addme"; //That is it!
//Add to an array
var array1 [1,2,3,4,5];
array1[0] = "addme";
array[6] = null;
//We shouldn't mix strings, integers, and nulls in arrays, but this isn't a best-practice tutorial.
Remember the JS object syntax and you may start to see a whole new flexible world of objects open up. But it may take a bit.
Answer 3: Ah, yeah... how to merge.
There are seriously (very many) ways to merge two arrays. It depends on exactly what you need. Sorted, Duplicated, Concatenated... there are a few.
Here is the answer!
UPDATE: How to make a beautiful multiple dimensional array.
//Multiple Dimension Array
var array1 = [1,2,3];
var array2 = [3,4];
var arraysinArray = [array1,array2]; //That is it!
Here is the curve again, this could be in an object:
var obj{
array1:[1,2,3],
array2:[3,4]
}
JavaScript is powerful stuff, stick with it; it gets good. : )
Hope that helps,
All the best!
Nash
In this case, think of a JavaScript's object literal {} as being like PHP's associative array.
Given that, an "array of arrays" actually looks like this (using your above desired output):
{public: [["el29t7","3bmGDy"], ["aj19vA", "jO71Ba"]]}
So here we have an object literal with a single property named "public" whose value is a 2-dimensional array.
If we assign the above to a variable we can then push another array onto "public" like this:
var current_data = {public: [["el29t7","3bmGDy"], ["aj19vA", "jO71Ba"]]};
// Using direct property access
current_data.public.push(["t9t9t9", "r4r4r4"]);
// Or using bracket notation
current_data["public"].push(["w2w2w2", "e0e0e0"]);
current_data's value is now:
{public: [
["el29t7","3bmGDy"],
["aj19vA", "jO71Ba"],
["t9t9t9", "r4r4r4"],
["w2w2w2", "e0e0e0"]
]}
So now "public" is an array whose length is 4.
current_data.public[0]; // ["el29t7","3bmGDy"]
current_data.public[1]; // ["aj19vA", "jO71Ba"]
current_data.public[2]; // ["t9t9t9", "r4r4r4"]
current_data.public[3]; // ["w2w2w2", "e0e0e0"]
MDN has very good documentation on Array for insight on other functions you might need.
https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array
First is an object, that contains array, second is an array.
DEMO showing display output http://jsfiddle.net/GjQCV/
var object={"public":{"0":["el29t7","3bmGDy"]}};
var arr=["aj19vA", "jO71Ba"] ;
/* use object notation to add new property and value which is the array*/
object.public[1]=arr;
It'd be much more natural if {"0": ...} were a true array rather than an object, but anyway:
function maxKey(b) {
var max;
for( var key in b )
var max = key;
return max;
}
function merge(a,b) {
for( var key in a ) {
b[key] = b[key] ? (b[key][maxKey(b)+1]=a[key], b[key]) : a[key];
}
return b;
}
Note that this assumes you would insert at the next integer index
Arrays are a particular kind of Javascript object
JSON is a way of representing Javascript objects (and as such can represent arrays and more)
Objects are much more general, and can be simple objects that can be represented as JSON, or can contain functions and prototypes.
So, this is not an array of arrays (you would access items using JSON notation like myobj["0"]):
{"0":["el29t7","3bmGDy"], "1":["aj19vA", "jO71Ba"]}
This is an array of arrays, which means you can use the push method to add an item, and access items using array notation like myobj[0]:
[ ["el29t7","3bmGDy"], ["aj19vA", "jO71Ba"] ]
It seems like the structure you want is something like this:
var myobj = { "public": [ ["key", "value"], ["key", "value"] ] }
Then if you want to add/merge new items, you'd write this:
if (myobj["public"] != null) {
myobj["public"].push(["newkey", "newval"]);
} else {
myobj["public"] = ["newkey", "newval"];
}

In JavaScript, how do I access an object inherited from Array with the [] operator?

I have a situation, where I need to create a new JavaScript object that is inherited from Array. I am using the following code:
// Create constructor function.
var SpecialArray = function () {};
// Create intermediate function to create closure upon Array's prototype.
// This prevents littering of native Array's prototype.
var ISpecialArray = function () {};
ISpecialArray.prototype = Array.prototype;
SpecialArray.prototype = new ISpecialArray();
SpecialArray.prototype.constructor = SpecialArray;
// Use Array's push() method to add two elements to the prototype itself.
SpecialArray.prototype.push('pushed proto 0', 'pushed proto 1');
// Use [] operator to add item to 4th position
SpecialArray.prototype[4] = 'direct [] proto to 4';
// Create new instance of Special Array
var x = new SpecialArray();
// Directly add items to this new instance.
x.push('pushed directly on X');
x[9] = 'direct [] to 9'
console.log(x, 'length: ' + x.length);
Quite interestingly, the [] operation seem to be useless and the console output is:
["pushed proto 0", "pushed proto 1", "pushed directly on X"] length: 3
What am I missing here?
It is not possible to subclass the Array class and use t this way.
The best solution for you is to extend just the array class and use it as it is.
There are two other options that I do not like but they exist
http://ajaxian.com/archives/another-trick-to-allow-array-subclasses
http://dean.edwards.name/weblog/2006/11/hooray/
This is one of those that always trips people up. The length property only applies to the ordered elements. You can't extend an array then insert an arbitrary non-sequitous key and expect it to work. This is because the relationship between the length property and the array contents is broken once you extend the array. Pointy's link above does a very good job of explaining this in more detail.
To prove this add this to the end of your example:
console.log(x[4]);
As you can see your entry is present and correct, it's just not part of the ordered array.
Like everything else in javascript the Array object is just a Associative Array with string keys. Non numerical, non sequitous keys are hidden to fool you into thinking it's a 'proper' numerically indexed array.
This strange mixed design of the Array object does mean you can do some strange and wonderful things like storing ordered and unordered information in the same object. I'm not saying this is a good idea, I'm just saying it's possible.
As you will have noticed by now when iterating structures like this the non sequitous keys don't appear which makes sense for the general use case of arrays for ordered information. It's less useful, or in fact useless when you want to get keyed info. I would venture that if ordering is unimportant you should use an object not an array. If you need both ordered and unordered store an array as a property in an object.
The best way I have found to create a child prototype of an "Array" is to not make a child prototype of "Array" but rather create a child of an "Array-Like" prototype. There are many prototypes floating around that attempt to mimic the properties of an "Array" while still being able to "inherit" from it, the best one I've found is Collection because it preserves the ability to use brackets []. The major downfall is that it doesn't work well with non-numeric keys (i.e. myArray["foo"] = "bar") but if you're only using numeric keys it works great.
You can extend this prototype like this:
http://codepen.io/dustinpoissant/pen/AXbjxm?editors=0011
var MySubArray = function(){
Collection.apply(this, arguments);
this.myCustomMethod = function(){
console.log("The second item is "+this[1]);
};
};
MySubArray.prototype = Object.create(Collection.prototype);
var msa = new MySubArray("Hello", "World");
msa[2] = "Third Item";
console.log(msa);
msa.myCustomMethod();

Categories