Javascript match changing the value of a different array - javascript

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.

Related

Speed of looping through an array vs. looping through an object

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>

For loop withoit indexes javascript

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);

How to loop through Nested Json Array with (JavaScript) for loop and display the text

This may be a fairly simple question but it's just not working for me no matter how many times I change the for loop around. So how would you loop through this array using a for loop in JavaScript?
var fielditems =[
[["News Tips"],["Opinions"],["MedMinutes"]],
[["Yes"],["No"],["Maybe"]],
[["How"],["Why"],["When"]]
];
This is what I have and it's not working. I used an alert to just test out the result but it's not even returning anything.
for(itemSet in fielditems){
var itemSetValues = fielditems[itemSet];
for(set in itemSetValues){
var itemValue = itemSetValues[set];
for(value in itemvalue){
alert(itemValue[value]);
}
}
}
What am I doing wrong?
Don't use for() with in for arrays. It's for object properties. Use the standard format instead.
Demo: http://jsfiddle.net/ThinkingStiff/EVWch/
Script:
var fielditems =[
[["News Tips"],["Opinions"],["MedMinutes"]],
[["Yes"],["No"],["Maybe"]],
[["How"],["Why"],["When"]]
];
for( var itemIndex = 0; itemIndex < fielditems.length; itemIndex++ ){
var itemSetValues = fielditems[itemIndex];
for(var setIndex = 0; setIndex < itemSetValues.length; setIndex++ ){
var itemValue = itemSetValues[setIndex];
for(var valueIndex = 0; valueIndex < itemValue.length; valueIndex++ ){
alert(itemValue[valueIndex]);
};
};
};
​
Firstly, console is your friend. You get error ReferenceError: itemvalue is not defined because javascript is case sensitive. Change itemvalue in the most nested loop to itemValue.
Secondly, if you want iterate thorugh an array, you should use for-loop instead for-in-loop
Don't use for-in loops on arrays
Don't use (running) variables without declaring them as local
for (var i=0; i<fielditems.length; i++) {
var itemSetValues = fielditems[i];
for (var j=0; j<itemSetValues.length; j++) {
var itemvalue = itemSetValues[j]; // notice the case
for (var k=0; k<itemvalue.length; k++) {
alert(itemvalue[k]);
}
}
}
for..in is for objects ({}), not for arrays ([]).
You need to use a standard for loop.
for(var i = 0, iLen = fielditems.length; i < iLen; i++){
var iItem = fielditems[i];
for(var j = 0, jLen = iItem.length; j < jLen; j++){
var jItem = iItem[j];
alert(jItem[0]); // you can also add another loop here, if this will have more elements
}
}
NOTE:
for(var i = 0, iLen = fielditems.length; i < iLen; i++)
is better than:
for(var i = 0; i < fielditems.length; i++)
because fielditems.length isn't requested each loop, just once at the start.

Adding to array in for loop doesn't store value properly?

OK.. I really must be crazy. Why would these not print out 3-5 for "a"? I've tried two different methodologies to have the array store 3-5 below, and both of them seem.. obvious. There must be something in the underlying translation that I'm just not seeing.
<script>
var articlesKey = [];
for(var i = 3; i < 6; i++) {
articlesKey.push(i);
document.write('<br>i:'+i);
}
for (a in articlesKey)
document.write("<br>a:"+a);
articlesKey = [];
var count = 0;
for(var i = 3; i < 6; i++) {
articlesKey[count] = i;
document.write('<br>i:'+i);
count++;
}
for (a in articlesKey)
document.write("<br>a:"+a);
</script>
It prints out:
i:3
i:4
i:5
a:0
a:1
a:2
i:3
i:4
i:5
a:0
a:1
a:2
for( a in articlesKey) iterates a through the KEYS of articlesKey (letting you then get the values as articlesKey[a]). There is nothing wrong here.
That's very simply because a represents the array index in the loop, not the value at the index. Fix:
document.write("<br>a:"+articlesKey[a]);

What is the best way to do loops in JavaScript

I have stumbled into several methods of looping in JavaScript, what I like the most is:
for(var i = 0; i < a.length; i++){
var element = a[i];
}
But as tested here (http://www.robertnyman.com/2008/04/11/javascript-loop-performance/), it should probably be written so that the length is only calculated once.
In jQuery there is a .each that you can stick a function. I like this a little better, because I don't have to type the array twice, like in the above solution.
If JavaScript supported macros it would be a piece of cake to roll your own, but sadly it does not.
So what do you guys use?
I've started using iterators where relevant. Performance is reasonable, however more importantly it allows you to encapsulate the looping logic:
function createIterator(x) {
var i = 0;
return function(){
return x[i++];
};
}
Then to use:
var iterator=createIterator(['a','b','c','d','e','f','g']);
iterator();
returns "a";
iterator();
returns "b";
and so on.
To iterate the whole list and display each item:
var current;
while(current=iterator())
{
console.log(current);
}
Be aware that the above is only acceptable for iterating a list that contains "non-falsy" values. If this array contained any of:
0
false
""
null
NaN
the previous loop would stop at that item, not always what you want/expect.
To avoid this use:
var current;
while((current=iterator())!==undefined)
{
console.log(current);
}
Small improvement to the original, to only calculate the array size once:
for(var i = 0, len = a.length; i < len; i++){ var element = a[i]; }
Also, I see a lot of for..in loops. Though keep in mind that it's not technically kosher, and will cause problems with Prototype specifically:
for (i in a) { var element = a[i]; }
Just store the length in a variable first.
var len = a.length;
for (var i = 0; i < len; i++) {
var element = a[i];
}
I know I'm late to the party, but I use reverse loops for loops that don't depend on the order.
Very similar to #Mr. Muskrat's - but simplifying the test:
var i = a.length, element = null;
while (i--) {
element = a[i];
}
You could just always use a while loop, and compute the array limit before hand.
Var max = a.length-1;
var i = 0;
while(i <= max)
{
var element = a[i];
i++;
}
If you have many elements in the array and speed is an issue then you want to use a while loop that iterates from highest to lowest.
var i = a.length;
while( --i >= 0 ) {
var element = a[i];
// do stuff with element
}
I don't use it myself, but one of my colleagues uses this style:
var myArray = [1,2,3,4];
for (var i = 0, item; item = myArray[i]; ++i) {
alert(item);
}
like Ash's answer, this will hit issues if you've got "falsey" values in your array. To avoid that problem change it to (item = myArray[i]) != undefined
I don't see what the problem with using a standard for(;;) loop is.
A little test
var x;
var a = [];
// filling array
var t0 = new Date().getTime();
for( var i = 0; i < 100000; i++ ) {
a[i] = Math.floor( Math.random()*100000 );
}
// normal loop
var t1 = new Date().getTime();
for( var i = 0; i < 100000; i++ ) {
x = a[i];
}
// using length
var t2 = new Date().getTime();
for( var i = 0; i < a.length; i++ ) {
x = a[i];
}
// storing length (pollution - we now have a global l as well as an i )
var t3 = new Date().getTime();
for( var i = 0, l = a.length; i < l; i++ ) {
x = a[i];
}
// for in
var t4 = new Date().getTime();
for( var i in a ) {
x = a[i];
}
// checked for in
var t5 = new Date().getTime();
for( var i in a ) {
if (a.hasOwnProperty(i)) {
x = a[i];
}
}
var t6 = new Date().getTime();
var msg = 'filling array: '+(t1-t0)+'ms\n'+
'normal loop: '+(t2-t1)+'ms\n'+
'using length: '+(t3-t2)+'ms\n'+
'storing length: '+(t4-t3)+'ms\n'+
'for in: '+(t5-t4)+'ms\n'+
'checked for in: '+(t6-t5)+'ms';
console.log( msg );
results in:
filling array: 227ms
normal loop: 21ms
using length: 26ms
storing length: 24ms
for in: 154ms
checked for in: 176ms
So:- for in's take the longest, using the length property (which is a property and doesn't need to be calculated) is nearly as fast as storing it first - which is only a whisker slower than using an integer.
AND a for() is the usual way to loop over an array, which everyone expects and understands.
All of them add a variable to the scope they run in - i - which is a common name for this use and so shouldn't be used for other things. Storing the length first adds another var - l - to the scope, which is unnecesary
So, first you identify the perfect javascript loop, I believe it should look like this:
ary.each(function() {$arguments[0]).remove();})
This may require the prototype.js library.
Next, you get disgustet with the arguments[0] part and have the code be produced automatically from your server framework. This works only if the ladder is Seaside.
Now, you have the above generated by:
ary do: [:each | each element remove].
This comes complete with syntax completion and translates exactly to the above javascript. And it will make people's head spin that haven't used seasides prototype integration before, as they read your code. It sure makes you feel cool, too. Not to mention the gain in geekiness you can get here. The girls love it!

Categories

Resources