I'm not sure if this has been asked already, if it has, let me know in the comments and I'll delete the question. What's faster, looping through an object or looping through an array? For instance, if I have two arrays that are the exact same length(required for the script to run properly, not gonna get into details), each position in one array is associated with a position in the other array. So it looks like this:
var array_variable = ["get_ped_bridges", "get_rail_bridges"];
var array_url = ["http://eg.com/rest/services/Nope/MapServer/1", "http://eg.com/rest/services/Nope/MapServer/2"];
for(var j = 0; j < array_variable.length; j++){
console.log(array_variable[j], array_url[j]);
}
So as you can see, each url matches up to a position in the array_variable array. In an object, it would look something like this:
var object = {
one: {
variable: "get_ped_bridges",
url: "http://eg.com/rest/services/Nope/MapServer/1"
},
two: {
variable: "get_rail_bridges",
url: "http://eg.com/rest/services/Nope/MapServer/2"
}
}
So, if the lengths of both were substantially longer(the actual length would probably be around 20 positions), which loop would process faster?
The short answer is that generally an array is faster.
This is because of continuos indexing in an array, where it is always exactly known where the next element is (because it's stored contiguously)
you can refer to this previous answer for more info: Array vs. Object efficiency in JavaScript
<script src="http://broofa.com/Tools/JSLitmus/JSLitmus.js"></script>
<script>
JSLitmus.test('Array', function() {
var array_variable = ["get_ped_bridges", "get_rail_bridges"];
var array_url = ["http://eg.com/rest/services/Nope/MapServer/1", "http://eg.com/rest/services/Nope/MapServer/2"];
for (var j = 0, len = array_variable.length; j < len; j++) {
//
}
for (var j = 0, len = array_url.length; j < len; j++) {
//
}
});
JSLitmus.test('Object', function() {
var object = {
one: {
variable: "get_ped_bridges",
url: "http://eg.com/rest/services/Nope/MapServer/1"
},
two: {
variable: "get_rail_bridges",
url: "http://eg.com/rest/services/Nope/MapServer/2"
}
};
for (var i in object) {
//
}
});
</script>
Related
I have both an object and an array:
var elementsArr = [];
var elements = {
polygon: 734,
infoContent: "huhu",
id: 0
}
I am going to have multiple "elements" and push each one into "elementsArr".
for(var i=0; i<20; i++){
elements.id = id +=1;
elementsArr.push(elements);
}
My problem now is how to access a specific "id" within the object elements, within the array elementsArr and pushing this into another array.
I tried this but it doesn't seem to be working:
var ids = [];
for(var m=0; m<elementsArr.length; m++){
if(elements.id == elementsArr[m]){
ids.push(elements.id);
}
How do I do this?
Your code is pushing the same object onto the array over and over again.
One way to fix that would be to write a function to get a new element:
function Element(id) {
return {
polygon: 734,
infoContent: "huhu",
id: id
};
}
for(var i=0; i<20; i++){
elementsArr.push(Element(i));
}
If there are going to be a lot of elements, and the "id" values are all relatively small numbers, you'd be better off storing the elements such that the "id" is also the index:
for (var i = 0; i < 20; i++)
elementsArr[i] = Element(i);
To get the element with "id" 17, then:
var element17 = elementsArr[17];
If you really want to search, however, you can use .find():
var element17 = elementsArr.find(function(elem) { return elem.id === 17; });
or a simple loop:
for (var i = 0; i < elementsArr.length; ++i) {
if (elementsArr[i].id === 17) {
// found it!
}
}
You can extract the "id" values from the array with a simple call to .map():
var ids = elementsArr.map(function(elem) { return elem.id; });
or another for loop:
var ids = [];
for (var i = 0; i < elementsArr.length; ++i)
ids.push(elementsArr[i].id);
There are a couple of ways to do this. If you are able to work in ES6 then a WeakMap would be great.
However, I'm going to give you an ES5 instead.
Option 1 Loop through the data.
If you aren't accessing the data often, then looping through as you've done so may be the best choice.
Option 2 Set up your own index
On the other hand, if you need faster lookup, you can set up your own separate index to look things up.
var elementsLookup = {}; // Create an empty object.
for(var i=0; i<20; i++){
elements.id = id +=1;
elementsLookup[id] = elements; // Stash off a copy
elementsArr.push(elements);
}
Then you can look things up with a
var elem = elementsLookup[2]; // Get the element with an id of 2.
It is easy to do it with Array prototyping. Here is a function findById
Array.prototype.findById = function(id){
for(var x = 0 ; x < this.length; x++){
if(this[x].id == id){
return this[x];
}
}
return false;
}
You can use this function to recieve any id from the array or false if it does not exists
elementsArr.findById(17);
I want to display an array without showing of indexes. The for loop returns the array indexes which is not showing in usual declaration.
I want to send an array like [1,2,3 ...] but after retrieving from for loop, I haven't the above format. How can I store my values as above.
var a = [];
for (var i = 1; i < 8; i++) {
a[i] = i;
};
console.log(a);
Outputs:
[1: 1, 2: 2 ...]
Desired output:
[1,2,3]// same as console.log([1,2,3])
Array indices start at zero, your loop starts at 1, with index 0 missing you have a sparse array that's why you get that output, you can use push to add values to an array without using the index.
var a = [];
for (var i = 1; i < 8; i++) {
a.push(i);
};
console.log(a);
The problem is that you start your array with 1 index, making initial 0 position being empty (so called "hole" in array). Basically you treat array as normal object (which you can do of course but it defeats the purpose of array structure) - and because of this browser console.log decides to shows you keys, as it thinks that you want to see object keys as well as its values.
You need to push values to array:
var a = [];
for (var i = 1; i < 8; i++) {
a.push(i);
};
I have to disagree with the answers provided here. The best way to do something like this is:
var a = new Array(7);
for (var i = 0; i < a.length; i++) {
a[i] = i + 1;
}
console.log(a);
Your code is making each index equal to i, so use it this way
var a = [];
for (var i = 1; i < 8; i++) {
a.push(i);
};
console.log(a);
I have multiple keys in my localstorage: task-1,task-2, task-3 ... I'm searching a way to get the total of the keys starting with the string "tasks-" in order to place it in my loop instead of localStorage.length.
In fact if I have an other app that uses the localstorage, my loop returns me a length corresponding to ALL the keys in the localStorage, including the ones that are out of the app in question.
i=0;
if(localStorage.getItem("task-"+i) != null){
for( i = 0; i < localStorage.length; i++){
console.log(i)
}
}
Thanks a lot for your help
If you control the creation of these items, it would make much more sense to store them in an object and use JSON to convert between object and string:
var tasksObject = {
task1: ...,
task2: ...,
...
};
window.localStorage.setItem('tasks', JSON.stringify(tasksObject));
... later ...
var tasks = JSON.parse(window.localStorage.getItem('tasks'));
for (var task in tasks) {
// do stuff
}
The statements should be switched. Loop over everything and see if each item matches your condition.
var count = 0;
for(i = 0; i < localStorage.length; i++){
if(localStorage.getItem("task-"+i) != null){
console.log(i)
count++;
}
}
// count contains number of items beginning with task
var i, e, tasks=[];
for (i=0; (e=localStorage["task-"+i])!==undefined; i++) {
console.log(e);
tasks.push(e);
}
And how about
localStorage['num-tasks'] = tasks.length;
I have an array:
deleteIds= ["User1"];
and try to iterate over it as like:
first one:
for (var index = 0; index < len; index++) {
alert(deleteIds[index]);
}
second one:
for (var index in deleteIds) {
alert(deleteIds[index]);
}
What is the performance comparison of them?
This is a micro optimisation at best. Unless you have hundreds of thousands of elements in your deleteIds array, you should not be looking at optimising this.
It turns out that the for(;;;) version is quicker than for in: http://jsperf.com/iterating-over-a-loop/2 (thanks to #Jamiec for the jsperf).
However, what's more important than the performance comparison of these, is that both code snippets are functionally different to each other (live example).
var array = new Array(100);
for (var i = 0; i < array.length; i++) {
console.log(i); // shows 0 - 99
}
for (var x in array) {
console.log(x); // shows nothing
}
Furthermore, if you add methods to either the array, or to an object in the arrays' prototype chain, they will show up in the for (var x in y) loop, but not in for (;;;); (live example):
Array.prototype.foo = function() {};
var array = [];
for (var i = 0; i < array.length; i++) {
console.log(i); // nothing
}
for (var x in array) {
console.log(x); // `foo`
}
You can use hasOwnProperty to eliminate the attributes inherited from the prototype chain, but that won't stop you receiving methods directly on the object (live example):
Array.prototype.foo = function() {};
var array = [];
array.bar = function () {};
for (var i = 0; i < array.length; i++) {
console.log(i); // nothing
}
for (var x in array) {
if (array.hasOwnProperty(x)) {
console.log(x); // `bar`
}
}
It is because of these reasons that using for in for iterating over an array is discouraged, and the for(;;;) version should always be used instead. for in should be used for iterating over an object.
I am having issues with a couple arrays below and the match method. On my page I call the Checkout() function and it sets a temporary array equal to the array I've been building with different options. It then loops through the temporary array and removes html from one of the elements. The issue is that when I alert the array Remote.Cart.products before the loop it is exactly as it was built, but when I call the function again the exact same alert shows the new updated values even though I am not modifying the Remote.Cart.products array anywhere in the function.
function Checkout() {
tmp = null;
tmp = Remote.Cart.products;
alert( Remote.Cart.products );
for ( i = 0, li = tmp.length; i < li; i++ ) {
for ( j = 0, lj = tmp[ i ][1].length; j < lj; j++ ) {
tmp[ i ][1][j][1] = tmp[ i ][1][j][1].match(/<a\s+[^>]*href="([^\"]*)"[^>]*>(.*)<\/a>/i)[2];
}
}
}
Your help / insight is much appreciated!
You are using the same array. Just a different variable that points to the same array. In memory it's the same object.
You need to rebuild the array in your loop so that you can get an identical but new array.
More info on copying arrays and other objects can be found here: http://my.opera.com/GreyWyvern/blog/show.dml/1725165
Clint, you have to understand that tmp and Remote.Cart.products are different names for the same array. If you want to clone the array, do:
var tmp = [];
for(var i = 0; i < Remote.Cart.products.length; i++)
{
tmp[i] = []
for(var j = 0; j < Remote.Cart.products[i].length; j++)
{
tmp[i][j] = [];
for(var k = 0; k < Remote.Cart.products[i][j].length; k++)
{
tmp[i][j][k] = Remote.Cart.products[i][j][k].slice();
}
}
}
EDIT: Nesting corrected thanks to Squeegy
"even though I am not modifying the Remote.Cart.products array anywhere in the function"
tmp = Remote.Cart.products;
...
tmp[ i ][1][j][1] = ...
It sure looks like you are.