PDA

View Full Version : Search/Filter a Non-Numeral Array in Javascript



commoncorvid
01-16-2009, 05:27 PM
I'm new to Javascript as of last month, so I apologize for asking this completely basic question.

Say I have an array like this:

var shoearray [];
shoearray[0] = "blue shoes";
shoearray[1] = "new blue shoes";
shoe array[2] = "orange shoes";
shoe array[3] = "new orange shoes";
shoe array[4] = "red shoes"
shoe array[5] = "green shoes new";

I want to filter or search it and return a new array containing ONLY the "new" shoes. So output (in the form of a new array) would be:

new blue shoes, new orange shoes, green shoes new

I've been trying to use the .filter method, but am not sure how to specify that it should return only the elements containing the word "new". I understand regular expressions like "/new/ig" but can't quite figure out how to get that last link between filter and producing the new array.

Sorry for such a simple question. As you can tell, I'm a total noob. Hopefully someone can let me know what I'm either doing wrong, or what I need to use to make it work. Links to an instructional website are fine too!

Thanks a lot.

vwphillips
01-16-2009, 06:20 PM
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">

<head>
<title></title>
</head>

<body>
<script type="text/javascript">
/*<![CDATA[*/
var shoearray=[];
shoearray[0] = "blue shoes";
shoearray[1] = "new blue shoes";
shoearray[2] = "orange shoes";
shoearray[3] = "new orange shoes";
shoearray[4] = "red shoes"
shoearray[5] = "green shoes new";


for (var z0=0;z0<shoearray.length;z0++){
if (shoearray[z0].match(/\bnew\b/)){ // the \b is a word boundary
alert(shoearray[z0]);
}
}

/*]]>*/
</script>
</body>

</html>

commoncorvid
01-16-2009, 07:05 PM
Thank you very much!

Twey
01-16-2009, 08:30 PM
The idea of using regex and \b is fine, but it's better to abstract things out into functions where possible. In this case, it's possible to write a completely general function that takes a function telling it whether to keep an item. The usual name for this function is 'filter', and it's very useful in all sorts of situations — so useful, in fact, that it's built-in as of Javascript 1.6. Unfortunately, IE doesn't support this yet, so we have to roll our own anyway.
// Our filter function.
// We've put it on Array, for neatness.
Array.filter = function(f, a) {
// Iterate over our 'array' a (it needn't really be an array, so
// this will work on NodeLists and the like too). r is the new
// array we'll be returning.
for (var i = 0, n = a.length, r = []; i < n; ++i)
// We pass the key as the second argument, as well. If the
// function we pass to filter() doesn't care about this, it can
// ignore it.
if (f(a[i], i))
// Add the current element onto the end of r.
r[r.length] = a[i];

return r;
};

// map() is a function in a similar vein, but rather than deciding
// whether to keep elements, it simply applies a function to each
// one, transforming them. Also built-in as of JS1.5.
Array.map = function(f, a) {
for (var i = 0, n = a.length, r = []; i < n; ++i)
r[i] = f(a[i], i);

return r;
};

var shoearray = ["blue shoes",
"new blue shoes",
"orange shoes",
"new orange shoes",
"red shoes",
"green shoes new"];

// Here's our predicate function to decide whether to keep an item.
function shoesAreNew(shoestring) {
return /\bnew\b/.test(shoestring);
}

// Here we use map() only for the side effect caused by alert().
Array.map(alert, Array.filter(shoesAreNew, shoearray));I opted to put these functions on Array and pass the collection to which they apply explicitly, rather than put them on prototype. This is for two reasons: firstly, it means I don't have to check whether I'm clobbering the built-in ones :), and secondly, it allows me to pass a non-array collection such as a NodeList directly, rather than doing Array.prototype.filter.call(myNodeList, myPredicate) as the Mozilla implementation requires. The Mozilla implementation is situated on the prototype, however, so to write it using those would look like this (note that forEach() differs from map() only in that it ignores the return values):
var shoeArray = ["blue shoes",
"new blue shoes",
"orange shoes",
"new orange shoes",
"red shoes",
"green shoes new"];

function shoesAreNew(shoestring) {
return /\bnew\b/.test(shoestring);
}

shoearray.filter(shoesAreNew).forEach(alert);

vwphillips: until IE has decent support for XHTML, you probably shouldn't recommend it to people — certainly not without a note about sending the proper Content-Type. Transitional DOCTYPEs are meant for the transition from HTML3 to HTML4, and shouldn't be used on new pages.