Continuously loop through array javascript
Show
Chapter 5. Working with Arrays and Loops5.0. IntroductionAn array is an ordered collection of elements. In JavaScript, an array can be created using formal object notation, or it can be initialized using literal notation, as demonstrated in the following code: var arrObject = new Array("val1", "val2"); // array as object var arrLiteral = ["val1", "val2"]; // array literal To the developer, there is no difference: you can invoke an A new var arrObject = new Array(); You can also create a new array that has some values: var arrObject = new Array("val1","val2"); You can create an array literal by using square brackets to hold the array values. For instance, you can define an array literal and assign it to a variable: var arrLiteral = ["val1","val2","val3"]; You can also create, and use, a literal array in a function or method call: someFunction("param1", ["val1","val2"]); Note, though, that when you pass a variable containing
an array literal to a function, it is passed by reference—the same as passing a variable holding an function chgArray(arr) { arr[0] = "surprise!"; } var newArray = new Array("val1", "val2"); var newLiteral = ["val1","val2"]; chgArray(newArray); chgArray(newLiteral); alert(newArray); // prints surprise!,val2 alert(newLiteral); // prints surprise!,val2 An array, whether literal or object, can hold values of different data types: var arrObject = new Array("val1", 34, true); // string, number, boolean var arrLiteral = [arrObject, "val2", 18, false); // object, string, number, boolean You can print out an array; the JavaScript engine will automatically convert the array into a string representation: alert(arrLiteral); // prints out val1,34,true,val2,18,false In this example, the JavaScript engine makes the array-to-string conversion for both the array literal and the array object contained as an element within the array literal. Array elements can be accessed directly, using square brackets containing their index (position in the array). In addition, array elements can be set using the same index, which automatically creates the array element if it doesn’t exist: var arrObject = new Array(); arrObject[0] = "cat"; // array now has one element alert(arrObject[0]); // prints cat Arrays in JavaScript are zero-based, which means the first element index is zero, and the last element is at the array length, minus 1: var farmAnimals = new Array("cat","dog","horse","pig"); alert(farmAnimals[0]); // print cat alert(farmAnimals[3]); // print pig Not all array elements have to be defined when created. For instance, if you create an array literal, you can use commas to delimit array elements that don’t yet exist: var arrLiteral = ["val1",,"val3"]; In this code, the second array element is currently To create an array of several undefined elements, you can provide an array length when creating an array: var largeCollection = new Array(100); // a new array with 100 undefined elements One you’ve created an array, using 5.1. Looping Through an Array
ProblemYou want to easily access all elements of an array. SolutionThe most common approach to accessing an array is to use a var mammals = new Array("cat","dog","human","whale","seal"); var animalString = ""; for (var i = 0; i < mammals. length; i++) { animalString += mammals[i] + " "; } alert(animalString); DiscussionA Sometimes, though, you don’t want to access every element of the array. For instance, you might want to traverse an array until you find either a specific element, or any element that meets (or doesn’t meet) a certain criteria. In these cases, you’ll want to use a var numArray = new Array(1,4,66,123,240,444,555); var i = 0; while (numArray[i] < 100) { alert(numArray[i++]); } Notice that the index counter,
5.2. Creating a Multidimensional ArrayProblemYou want to create a multidimensional array (an array of arrays). SolutionCreate an array in which each element is also an array. For example, to create an array with three elements, each of which is also an array of three elements containing, respectively, string, number, and array literals, use the code snippet in Example 5-1. Example 5-1. Creating a multidimensional array // set array length var arrayLength = 3; // create array var multiArray = new Array(arrayLength); for (var i = 0; i < multiArray.length; i++) { multiArray[i] = new Array(arrayLength); } // add items to first array index multiArray[0][0] = "apple"; multiArray[0][1] = "banana"; multiArray[0][2] = "cherry"; // second multiArray[1][0] = 2; multiArray[1][1] = 56; multiArray[1][2] = 83; // third multiArray[2][0] = ['test','again']; multiArray[2][1] = ['Java','script']; multiArray[2][2] = ['read','books']; alert(multiArray); // printed out in first index order alert(multiArray[2]); // prints out subarray alert(multiArray[2][2][0]); // individual item DiscussionMultidimensional arrays in JavaScript are
managed by creating a new array as an element within an existing array. The new array can be created as an In Example 5-1, an array, To access the array elements, use the square bracket notation, with each set of brackets used to address each level of the array. In the following code, the array contents are printed out via an alert window, after being converted to a string first, if necessary: alert(multiArray[2]); // prints out test,again,Java,script,read,books alert(multiArray[2][2]); // prints out read,books alert(multiArray[2][2][1]); // prints out books Multidimensional arrays are typically used to hold the data from a table structure, but how the structure is maintained is up to the developer. For instance, the developer can support an array structure in which the outer index reflects the columns, and the inner reflects the rows. As an example, Table 5-1 shows a simple five-column, three-row table containing a set of numbers. Table 5-1. Simple table with five columns and three rows and sample data
To create this in JavaScript using a multidimensional array, use the following code: var table = new Array(5); table[0] = [45.89, 4, 34, 9998.99, 56]; // first row table[1] = [3, 23, 99, 43, 2]; // second row table[2] = [1, 1, 0, 43, 67]; // third row Of course, this doesn’t take into account column and row headers. To add in the headers, just treat them as array data, making sure to incorporate them into the proper place in the array to reflect the table structure. NoteIn a multideveloper environment, it’s essential that there is agreement among the developers about whether table structure data is stored column-centric or row-centric. 5.3. Creating a String from an ArrayProblemYou want to create a single string from an array. SolutionUse the var fruitArray = ['apple','peach','lemon','lime']; var resultString = fruitArray.join('-'); // apple-peach-lemon-lime DiscussionThe var numberArray = [1,2,3,4,5]; // array literal containing number elements var resultString = numberArray.join('+'); // returns string with 1+2+3+4+5 If the delimiter parameter isn’t provided, a comma is inserted between array element values by default: var numberArray = [1,2,3,4,5]; var resultString = numberArray.join(); // returns string with 1,2,3,4,5 5.4. Sorting an ArrayProblemYou want to sort an array. SolutionUse the var fruitArray = ['strawberry','apple','orange','banana','lime']; alert(fruitArray.sort()); // returns apple,banana,lime,orange,strawberry DiscussionThe var numberArray = [4,13,2,31,5]; alert(numberArray.sort()); // returns 13,2,31,4,5 Though the array members in this example are numbers, they’re sorted in lexicographical (dictionary) order, not numerically. To do an actual numeric sort, use a custom sort function: function compareNumbers(a,b) { return a - b; } var numArray = [13,2,31,4,5]; alert(numArray.sort(compareNumbers)); // prints 2,4,5,13,31 The function subtracts the second parameter value from the first, and if the first is less than the second, a negative value is returned; otherwise, the value is positive. If the return value is less than zero, the sort index for the second parameter is set higher than the first parameter. If the value is greater than zero, the sort index for the first parameter is set higher than the other. If the value is exactly zero, the sort index for the two is unchanged. If the array elements contain strings that could be
converted to numbers, then the var numberArray=["34","4","5"]; alert(numberArray.sort(compareNumbers)); // prints 4,5,34 The var numberArray = [4,5,1,3,2]; numberArray.sort(); numberArray.reverse(); // array now has 5,4,3,2,1 5.5. Store and Access Values in OrderProblemYou want to store values in such a way that you can access the values in the order in which they were stored. SolutionTo store and
access values in the order in which they’re received, create a FIFO (first-in, first-out) queue. Use the JavaScript // create new array var queue = new Array(); // push on three entries queue.push('first'); queue.push('second'); queue.push('third'); // shift two entries alert(queue.shift()); // returns first alert(queue.shift()); // returns second alert(queue); // returns third DiscussionA queue is an array of elements that are added one at a time, and retrieved in a first-in, first-out order (FIFO). Think of a line at the bank: people go to the end when they arrive at the bank, and tellers help those in the front of the line, who have been there the longest. You could emulate this behavior using counter variables to hold the index of the last item added (the end), and the index of the last one retrieved (from the front), but luckily, the JavaScript The queue.push('first'); The array element count increments with each pushed element. The var elem = queue.shift(); The array element count decreases by one with each shifted element, as 5.6. Store and Access Values in Reverse OrderProblemYou want to store values in such a way that you can access the values in reverse order: access the most recently stored value first, then a LIFO (last-in, first-out) stack. SolutionTo access stored values in reverse order (last item added is accessed first), create a LIFO (last-in, first-out) stack. Use the JavaScript // create new array var queue = new Array(); // push on three entries queue.push('first'); queue.push('second'); queue.push('third'); // pop two entries alert(queue.pop()); // returns third alert(queue.pop()); // returns second alert(queue); // returns first DiscussionA stack is an array of elements, with each new element added to the top of the stack, and retrieved in a last-in, first-out (LIFO) order. Think of a stack of dishes: you add plates to the top as they’re washed, and retrieve them from the top when needed. You could use a variable holding an integer that tracks the end of the array after each addition and retrieval, but JavaScript provides the functionality we need. The queue.push('first'); The array element count increments with each pushed element. The var elem = queue.pop(); The array element count decreases by one with each
popped element, as 5.7. Create a New Array as a Subset of an Existing ArrayProblemYou want to create a new array from a segment of an existing array. If the array elements are objects, you want to keep both arrays in sync. SolutionUse the var origArray = new Array(4); origArray[0] = new Array("one","two"); origArray[1] = new Array("three","four"); origArray[2] = new Array("five","six"); origArray[3] = new Array("seven","eight"); // create new array using slice var newArray = origArray.slice(1,3); DiscussionThe If the copied elements are literal values, such as strings, numbers, and Booleans, they’re copied by value—changing the value in the old array has no impact on the same values in the new array, and vice versa. When objects are copied, though, they’re copied by reference, whether they’re copied via var first = new Array("one","two","three"); var second = first; // copied by reference second[1] = "apple"; // first and second arrays now have "one","apple","three" The code that follows demonstrates the object syncing when used with slice. A section of one array is used to create a new array with var origArray = new Array(4); origArray[0] = new Array("one","two"); origArray[1] = new Array("three","four"); origArray[2] = new Array("five","six"); origArray[3] = new Array("seven","eight"); var newArray = origArray.slice(1,3); alert(newArray); // prints out three,four,five,six // modify original origArray[1][0] = "octopus"; // print out new alert(newArray); // prints out octopus,four,five,six // modify new newArray[1][1] = "kitten"; // print out old alert(origArray); // prints out one,two,octopus,four,five,kitten,seven,eight Another handy use for var args = Array.prototype.slice.call(arguments); Using 5.8. Searching Through an ArrayProblemYou want to search an array for a specific value and get the array element index if found.
SolutionUse the new (ECMAScript 5) var animals = new Array("dog","cat","seal","elephant","walrus","lion"); alert(animals.indexOf("elephant")); // prints 3 DiscussionThough support for both var animals = new Array("dog","cat","seal","walrus","lion", "cat"); alert(animals.indexOf("cat")); // prints 1 alert(animals.lastIndexOf("cat")); // prints 5 Both methods can take a starting index, setting where the search is going to start: var animals = new Array("dog","cat","seal","walrus","lion", "cat"); alert(animals.indexOf("cat",2)); // prints 5 alert(animals.lastIndexOf("cat",4)); // prints 1 Currently, all of the book’s target browsers support
See AlsoAs mentioned, not all browsers support if (!Array.prototype.indexOf) { Array.prototype.indexOf = function(elt /*, from*/) { var len = this.length >>> 0; var from = Number(arguments[1]) || 0; from = (from < 0) ? Math.ceil(from) : Math.floor(from); if (from < 0) from += len; for (; from < len; from++) { if (from in this && this[from] === elt) return from; } return -1; }; } 5.9. Flatten a Multidimensional ArrayProblemYou want to flatten a multidimensional array into a single dimensional array. SolutionUse the var origArray = new Array(); origArray[0] = new Array("one","two"); origArray[1] = new Array("three","four"); origArray[2] = new Array("five","six"); origArray[3] = new Array("seven","eight"); // flatten array var newArray = origArray[0].concat(origArray[1],origArray[2],origArray[3]); alert(newArray[5]); // prints six DiscussionThe One use for this type of functionality is to return a single dimensional array made up of elements from a multidimensional array, as shown in the solution. 5.10. Search and Remove or Replace Array ElementsProblemYou want to find occurrences of a given value in an array, and either remove the element or replace with another value. SolutionUse the var animals = new Array("dog","cat","seal","walrus","lion", "cat"); // remove the element from array animals.splice(animals.indexOf("walrus"),1); // dog,cat,seal,lion,cat // splice in new element animals.splice(animals.lastIndexOf("cat"),1,"monkey"); // dog,cat,seal,lion,monkey DiscussionThe var animals = new Array("cat","walrus","lion", "cat"); // splice in new element animals.splice(-1,1,"monkey"); // cat,walrus,lion,monkey If the number of elements to splice is not provided, all elements from the index to the end will be removed: var animals = new Array("cat","walrus","lion", "cat"); // remove all elements after second animals.splice(2); // cat,walrus The last parameter, the replaced value, can be a set of replacement values, separated by commas: var animals = new Array("cat","walrus","lion", "cat"); // replace second element with two animals.splice(2,1,"zebra","elephant"); // cat,walrus,zebra,elephant,cat Removing or replacing one element is handy, but being able to remove or replace all instances of a particular
element is even handier. In Example 5-2, an array is created with several elements, including multiple instances of a specific value. The Example 5-2. Using looping and splice to replace and remove elements
The example works with all of this book’s target browsers except for IE8, which doesn’t currently support either See AlsoSee
Recipe 5.8 for a workaround for 5.11. Applying a Function Against Each Array ElementProblemYou want to use a function to check an array value, and replace it if it matches a given criterion. SolutionUse the new ECMAScript 5 var charSets = new Array("ab","bb","cd","ab","cc","ab","dd","ab"); function replaceElement(element,index,array) { if (element == "ab") array[index] = "**"; } // apply function to each array element charSets.forEach(replaceElement); alert(charSets); // prints **,bb,cd,**,cc,**,dd,** DiscussionIn the last section, we used a The First, the element’s value is tested to see if it matches a given string, NoteDon’t return a value from the function passed to the Chrome, Firefox, Opera, and Safari
support See AlsoThe concept of callback functions is covered in more detail in Chapter 6. Most modern browsers support if (!Array.prototype.forEach) { Array.prototype.forEach = function(fun /*, thisp*/) { var len = this.length >>> 0; if (typeof fun != "function") throw new TypeError(); var thisp = arguments[1]; for (var i = 0; i < len; i++) { if (i in this) fun.call(thisp, this[i], i, this); } }; } 5.12. Applying a Function to Every Element in an Array and Returning a New ArrayProblemYou want to convert an array of decimal numbers into a new array with their hexadecimal equivalents. SolutionUse the // function to convert decimal to hexadecimal function convertToHex(element,index,array) { return element.toString(16); } var decArray = new Array(23, 255, 122, 5, 16, 99); var hexArray = decArray.map(convertToHex); alert(hexArray); // 17,ff,a,5,10,63 Discussion
Like the The function that’s passed to the map method has three parameters: the current array element, the index for the array element, and the array. The See AlsoMost modern browsers support the For comprehensiveness, I’ve included the code for the workaround below. To use, include the code in a library function that is processed before the if (!Array.prototype.map) { Array.prototype.map = function(fun /*, thisp*/) { var len = this.length >>> 0; if (typeof fun != "function") throw new TypeError(); var res = new Array(len); var thisp = arguments[1]; for (var i = 0; i < len; i++) { if (i in this) res[i] = fun.call(thisp, this[i], i, this); } return res; }; } 5.13. Creating a Filtered ArrayProblemYou want to filter element values in an array and assign the results to a new array. SolutionUse the function removeChars(element,index,array) { return (element !== "**"); } var charSet = new Array("**","bb","cd","**","cc","**","dd","**"); var newArray = charSet.filter(removeChars); alert(newArray); // bb,cd,cc,dd DiscussionThe The function passed as parameter to the The
function has three parameters: the array element, the index for the element, and the array, itself. The See AlsoSupport for if (!Array.prototype.filter) { Array.prototype.filter = function(fun /*, thisp*/) { var len = this.length >>> 0; if (typeof fun != "function") throw new TypeError(); var res = new Array(); var thisp = arguments[1]; for (var i = 0; i < len; i++) { if (i in this) { var val = this[i]; // in case fun mutates this if (fun.call(thisp, val, i, this)) res.push(val); } } return res; }; } 5.14. Validating Array ContentsProblemYou want to ensure that an array meets certain criteria. SolutionUse the var elemSet = new Array("**",123,"aaa","abc","-",46,"AAA"); // testing function function textValue (element,index,array) { var textExp = /^[a-zA-Z]+$/; return textExp.test(element); } // run test alert(elemSet.every(textValue)); // false Or use the var elemSet = new Array("**",123,"aaa","abc","-",46,"AAA"); // testing function function textValue (element,index,array) { var textExp = /^[a-zA-Z]+$/; return textExp.test(element); } // run test alert(elemSet.some(textValue)); // true DiscussionThe The solution demonstrates that
the same callback function can be used for both the Which method to use depends on your needs. If all array elements must meet certain criteria, then use The callback function takes three parameters: the element, the index for the element, and the array. Neither the
See AlsoMost modern browsers support For comprehensiveness, I’ve also included the functionality below. To use, ensure that the script provided is processed before the methods are needed. Here’s how to emulate if (!Array.prototype.some) { Array.prototype.some = function(fun /*, thisp*/) { var i = 0, len = this.length >>> 0; if (typeof fun != "function") throw new TypeError(); var thisp = arguments[1]; for (; i < len; i++) { if (i in this && fun.call(thisp, this[i], i, this)) return true; } return false; }; } Here’s how to emulate
if (!Array.prototype.every) { Array.prototype.every = function(fun /*, thisp*/) { var len = this.length >>> 0; if (typeof fun != "function") throw new TypeError(); var thisp = arguments[1]; for (var i = 0; i < len; i++) { if (i in this && !fun.call(thisp, this[i], i, this)) return false; } return true; }; } 5.15. Using an Associative Array to Store Form Element Names and ValuesProblemYou want to store form element names and values, for later validation purposes. SolutionUse an associative array to store the elements, using the element identifiers as array index: var elemArray = new Object(); // notice Object, no Array var elem = document.forms[0].elements[0]; elemArray[elem.id] = elem.value; Iterate over the array using the for (var key in elemArray) { str+=key + "," + elemArray[key] + " "; } DiscussionMost JavaScript arrays use a numeric index, such as the following: arr[0] = value; However, you can create an associative array in JavaScript, where the array index can be a string representing a keyword, mapping that string to a given value. In the solution, the array index is the identifier given the array element, and the actual array value is the form element value. You can create an associative array, but you’re not using the The earlier Prototype.js library made an assumption that most array use in JavaScript is numeric index–based, like most of the earlier examples in this chapter. The library
extended the It’s not that Prototype.js was “breaking” JavaScript. The When
we use an obj[propName] = "somevalue"; what you’re really doing is adding a new object property: obj.propName = "somevalue"; To further
demonstrate how different the associative array is from a numeric-based array, when you use an Instead of using an Example 5-3 shows a web page. Here, when the form is submitted, all of the form elements of type text are accessed and stored in an associative array. The element IDs are used as the array keyword, and the values assigned to the array elements. Once collected, the associative array is passed to another function that could be used to validate the values, but in this case just creates a string of keyword/value pairs, which is then displayed. Example 5-3. Demonstrating associative array with form elements
In the example, notice that the array index is formed by the form element’s for (keyword in array) This syntax accesses the array index, which is then assigned to the keyword variable that can be used to access the array value: for (keyword in array) var a = array[keyword]; Figure 5-1 shows the example after values are typed into the form fields and the form is submitted. Figure 5-1. Demonstration of associative array and traversing form elements This type of keyword/value pairing is commonly referred to as a hash map or hash table, though the JavaScript functionality isn’t a true hash map functionality. The reason why it isn’t a true hash map is that it doesn’t account for the fact that the same keyword could be used with multiple values, and the JavaScript version only accepts strings as keywords. |