In Ruby you can make an array of arrays (which can represent a grid) by doing the following
#grid = Array.new(num_rows) {Array.new(num_columns)}
Is there an equivelent with Javascript?
Or do you need to create the first array and iterate over it, explicitly creating a new array at each index?
e.g.
this.grid = new Array(this.numRows);
for (var i = 0; i < this.numRows; i++) {
this.grid[i] = new Array(this.numColumns);
}
I am using Underscore.js so could leverage its methods if needs be
There may be something better in underscore, but the following will work. I used 3 and 4 because for the height/width just so I could see the results in this fiddle.
array = _.map(_.range(3), function(){return _.range(4)});
You might want to add the underscore tag to get some underscore eyes on the question.
In JavaScript you can have different objects at different elements of an array. It's as simple as
var myArray = new Array()
myArray[0] = new Array()
You can do that as many times as you like to set up size of the 2D space you want to create. Use loops to set them up if your space is large. I don't know what objects you want in your array or I'd be more specific.
It just as easy to access this structure as in any other language: myArray[58][12]
This question is also relevant.
Related
Struggling with some javascript array manipulation/updating. Hope someone could help.
I have an array:
array('saved_designs'=array());
Javascript JSON version:
{"saved_design":{}}
I will be adding a label, and associated array data:
array("saved_designs"=array('label'=array('class'='somecssclass',styles=array(ill add more assoc elements here),'hover'=array(ill add more assoc elements here))))
Javascript version:
{"saved_designs":{"label":{"class":"someclass","style":[],"hover":[]}}}
I want to be able to append/modify this array. If 'label' already defined...then cycle through the sub data for that element...and update. If 'label' doesnt exist..then append a new data set to the 'saved_designs' array element.
So, if label is not defined, add the following to the 'saved_designs' element:
array('label2' = array('class'=>'someclass2',styles=array(),'hover=>array()')
Things arent quite working out as i expect. Im unsure of the javascript notation of [], and {} and the differences.
Probably going to need to discuss this as answers are provided....but heres some code i have at the moment to achive this:
//saveLabel = label the user chose for this "design"
if(isUnique == 0){//update
//ask user if want to overwrite design styles for the specified html element
if (confirm("Their is already a design with that label ("+saveLabel+"). Overwrite this designs data for the given element/styles?")) {
currentDesigns["saved_designs"][saveLabel]["class"] = saveClass;
//edit other subdata here...
}
}else{//create new
var newDesign = [];
newDesign[saveLabel] = [];
newDesign[saveLabel]["class"] = saveClass;
newDesign[saveLabel]["style"] = [];
newDesign[saveLabel]["hover"] = [];
currentDesigns["saved_designs"].push(newDesign);//gives error..push is not defined
}
jQuery("#'.$elementId.'").val(JSON.stringify(currentDesigns));
thanks in advance. Hope this is clear. Ill update accordingly based on questions and comments.
Shaun
It can be a bit confusing. JavaScript objects look a lot like a map or a dictionary from other languages. You can iterate over them and access their properties with object['property_name'].
Thus the difference between a property and a string index doesn't really exist. That looks like php you are creating. It's called an array there, but the fact that you are identifying values by a string means it is going to be serialized into an object in javascript.
var thing = {"saved_designs":{"label":{"class":"someclass","style":[],"hover":[]}}}
thing.saved_designs.label is the same thing as thing["saved_designs"]["label"].
In javascript an array is a list that can only be accessed by integer indices. Arrays don't have explicit keys and can be defined:
var stuff = ['label', 24, anObject]
So you see the error you are getting about 'push not defined' is because you aren't working on an array as far as javascript is concerned.
currentDesigns["saved_designs"] == currentDesigns.saved_designs
When you have an object, and you want a new key/value pair (i.e. property) you don't need a special function to add. Just define the key and the value:
**currentDesigns.saved_designs['key'] = newDesign;**
If you have a different label for every design (which is what it looks like) key is that label (a string).
Also when you were defining the new design this is what javascript interprets:
var newDesign = [];
newDesign is an array. It has n number of elements accessed by integers indices.
newDesign[saveLabel] = [];
Since newDesign is a an array saveLabel should be an numerical index. The value for that index is another array.
newDesign[saveLabel]["class"] = saveClass;
newDesign[saveLabel]["style"] = [];
newDesign[saveLabel]["hover"] = [];
Here explicitly you show that you are trying to use an array as objects. Arrays do not support ['string_key']
This might very well 'work' but only because in javascript arrays are objects and there is no rule that says you can't add properties to objects at will. However all these [] are not helping you at all.
var newDesign = {label: "the label", class: saveClass};
is probably what you are looking for.
I have a scenario, where I have two different Objects.
Scenario to achieve:
From two objects I need to match the values which has "A1","B2", etc...
Since both the objects values are not in proper order, the loop is breaking and missing some values.
In my demo the object1 has same repeated value i.e. "C3", It should be displayed only once.
Final output required is I need to detect only the matched values from two objects and display its corresponding "a" and "b values."
I have tried almost 90%, but somewhere some minor error is breaking my loop, Please help me out.
Sample code:
for(var i=0;i<obj1.results[0].loc.length;i++){
var findA = obj1.results[0].loc[i].anc[0].title;
for(var j=0;j< obj2.ILoc.length;j++){
var findB = obj2.ILoc[j].ais;
if(findA == findB) {
var a = obj1.results[0].loc[i].a;
var b = obj1.results[0].loc[i].b;
console.log(a);
console.log(b);
}
}
}
This is what I have tried:
Demo Link
I would recommend using for...in loop, since you're using objects instead of arrays.
for (variable in object) {...
}
If length property of both objects is equal, then this kind of loop alone will help you to compare objects with ease.
I would recommend using the diff module. You can use it in node.js and the browser.
I am attempting to merge two arrays of objects to so I can validate a form. The usual concat method does not appear to work in this circumstance. Concat works with ordinary numerical and string arrays but doesn't with object arrays. The line var allTags = allInputs.concat(allSelects); does not work.
var allInputs = document.getElementsByTagName("input");
alert("Inputs: " + allInputs.length);
var allSelects = document.getElementsByTagName("select");
alert("Selects: " + allSelects.length);
var allTags = allInputs.concat(allSelects);
alert("allTags: " + allTags.length);
Concat works with ordinary numerical and string arrays but doesn't with object arrays.
Actually, it does, but NodeList instances don't have a concat method, and Array#concat doesn't have a means of identifying that you want to flatten those (because they're not arrays).
But it's still fairly easy to do (see caveat below, though). Change this line:
var allTags = allInputs.concat(allSelects);
to
var allTags = [];
allTags.push.apply(allTags, allInputs);
allTags.push.apply(allTags, allSelects);
Live Example | Source
That works by using a bit of a trick: Array#push accepts a variable number of elements to add to the array, and Function#apply calls the function using the given value for this (in our case, allTags) and any array-like object as the arguments to pass to it. Since NodeList instances are array-like, push happily pushes all of the elements of the list onto the array.
This behavior of Function#apply (not requiring the second argument to really be an array) is very clearly defined in the specification, and is well-supported in modern browsers.
Sadly, IE6 and 7 don't support the above (I think it's specifically using host objects — NodeLists — for Function#apply's second argument), but then, we shouldn't be supporting them, either. :-) IE8 doesn't, either, which is more problematic. IE9 is happy with it.
If you need to support IE8 and earlier, sadly, I think you're stuck with a boring old loop:
var allInputs = document.getElementsByTagName('input');
var allSelects = document.getElementsByTagName('select');
var allTags = [];
appendAll(allTags, allInputs);
appendAll(allTags, allSelects);
function appendAll(dest, src) {
var n;
for (n = 0; n < src.length; ++n) {
dest.push(src[n]);
}
return dest;
}
Live Example | Source
That does work on IE8 and earlier (and others).
document.get[something] returns a NodeList, which looks very similar to an Array, but has numerous distinctive features, two of which are:
It does not contain the concat method
The list of items is live. This means they change as the document changes in real time.
If you don't have any issues with turning your NodeLists into actual arrays, you could do the following to achieve the effect you desire:
var allInputs = document.getElementsByTagName("input")
, allSelects = document.getElementsByTagName("select")
;//nodeLists
var inputList = makeArray(allInputs)
, selectList = makeArray(allSelects)
;//nodeArrays
var combined = inputList.concat(selectList);
function makeArray(list){
return Array.prototype.slice.call(list);
}
You will lose any and all behaviors of the original NodeList, including it's ability to update in real time to reflect changes to the DOM, but my guess is, that's not really an issue.
What you're dealing with are HTMLCollections, and they're live collections (i.e., when you add a node to the DOM, it's automatically added to the collection.
And sadly, it doesn't have a concat method... for a reason. What you need to do is to convert it to an array, losing its live behaviour:
var allInputsArray = [].slice.call(allInputs),
allSelectsArray = [].slice.call(allSelects),
allFields = allInputsArray.concat(allSelectsArray);
I found a simple way to collect dom objects in the order they appear on a page or form.
Firstly, create a dummy class style 'reqd' on the object then use the following which creates a list in the order they appear on the page. Just add the class to any objects you wish to collect.
var allTags = document.querySelectorAll("input.reqd, select.reqd");
Looked into underscore.js at all? You could do
var allSelectsAndInputs = _.union(_.values(document.getElementsByTagName("input")),_.values(document.getElementsByTagName("select")));
For more information see: http://underscorejs.org/#extend
The function is intended for objects, but works in this setting.
I have this collection of images resources where that is stored in array, the user will select an image and then the selected image will be removed from the list(also from the array) and after that The array would be rearrange. How could I perform such task? (as much as possible I do not want to use an open source library)
Sounds like you need to look up splice() method. It allows you to add and remove one to many items within an array at any index.
here's reference for it.
https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/Array/splice
your question lacks a code example but you can use Array.splice(index,number) whereas index is zero based and number is how many items to remove.
images.splice(selectedIndex,1);
Simply, you can create a temporary array where you store the initial array elements you need and reassign the value of your initial array to the temporary array.
function clean_array(my_array){
var no_need_value = 'value you want to remove'
var tmpArray = new Array()
for (var i = 0; i < my_array.length; i++)
if (my_array[i] != no_need_value)
tmpArray.push(my_array[i])
my_array = tmpeArray
}
I am dynamically building an array of objects using a process that boils down to something like this:
//Objects Array
var objects = [];
//Object Structure
var object1 = {"id":"foobar_1", "metrics":90};
var object2 = {"id":"some other foobar", "metrics":50};
objects[0] = object1;
objects[1] = object2;
(Let it be said for the record, that if you can think of a better way to dynamically nest data such that I can access it with objects[i].id I am also all ears!)
There's ultimately going to be more logic at play than what's above, but it's just not written yet. Suffice it to say that the "object1" and "object2" parts will actually be in an iterator.
Inside that iterator, I want to check for the presence of an ID before adding another object to the array. If, for example, I already have an object with the ID "foobar_1", instead of pushing a new member to the array, I simply want to increment its "metrics" value.
If I wasn't dealing with an array of objects, I could use inArray to look for "foobar_1" (a jQuery utility). But that won't look into the object's values. The way I see it, I have two options:
Keep a separate simple array of just the IDs. So instead of only relying on the objects array, I simply check inArray (or plain JS equivalent) for a simple "objectIDs" array that is used only for this purpose.
Iterate through my existing data object and compare my "foobar_1" needle to each objects[i].id haystack
I feel that #1 is certainly more efficient, but I can't help wondering if I'm missing a function that would do the job for me. A #3, 4, or 5 option that I've missed! CPU consumption is somewhat important, but I'm also interested in functions that make the code less verbose whether they're more cycle-efficient or not.
I'd suggest switching to an object instead of an array:
var objects = {};
objects["foobar_1"] = {metrics: 90};
objects["some other foobar"] = {metrics: 50};
Then, to add a new object uniquely, you would do this:
function addObject(id, metricsNum) {
if (!(id in objects)) {
objects[id] = {metrics: metricsNum};
}
}
To iterate all the objects, you would do this:
for (var id in objects) {
// process objects[id]
}
This gives you very efficient lookup for whether a given id is already in your list or not. The only thing it doesn't give you that the array gave you before is a specific order of objects because the keys of an object don't have any specific order.
Hmm , i wonder why dont you use dictionary cause that is perfectlly fits your case. so your code will be as below:
//Objects Array
var objects = [];
//Object Structure
var object1 = {"metrics":90};
var object2 = {"metrics":50};
objects["foobar_1"] = object1;
objects["some other foobar"] = object2;
// An example to showing the object existence.
if (!objects["new id"]){
objects["new id"] = {"metrics": 100};
}
else {
objects["new id"].matrics++;
}