Go Back   CodingForums.com > :: Client side development > JavaScript programming > Post a JavaScript

Before you post, read our: Rules & Posting Guidelines

Reply
 
Thread Tools Rate Thread
Enjoy an ad free experience by logging in. Not a member yet? Register.
Old 11-10-2011, 04:34 PM   PM User | #1
rnd me
Senior Coder

 
rnd me's Avatar
 
Join Date: Jun 2007
Location: Urbana
Posts: 3,468
Thanks: 9
Thanked 466 Times in 450 Posts
rnd me is a jewel in the roughrnd me is a jewel in the roughrnd me is a jewel in the rough
Lightbulb simple list filtering

intro
Filtering lists is usually done by hand with some setup involving a valid item collector, a for loop and one or more conditionals.
That works, but is quite a bit to type out, and i've discovered a very simple way to do so using native javascript statements. I noticed it re-reading the spec last month, and it's already saved me a lot of code writing on a data-centric web server backend, so i thought i'd share the trick here.


about
the secret is using the generic potential of RegExp's test() method to filter the results. Since RegExp().test(strData) returns true or false, it's perfect for feeding Array.filter().


code examples (live demo):
Code:
//example text data (from Tom Sawyer) :
var text="WITHIN a few minutes the news had spread, and a dozen skiff-loads of men were on their way to McDougal's cave, and the ferryboat, well filled with passengers, soon followed. Tom Sawyer was in the skiff that bore Judge Thatcher."


//example array: an array with each slot holding one word from above :
var words=text.split(/[\s,.]+/);


alert("All words \n"+ 

  words.join("\n")
);




alert("Words that are 5 or more letters long \n"+ 

  words.filter( RegExp().test,  /\w{5,}/ ).join("\n")
);




alert("Words starting with a vowel \n"+ 

  words.filter( RegExp().test,  /^[aeiou]/i ).join("\n")
);



boring details:
A minor technical glitch is that Array.filter separates the method from the context, which means that a .test method on a RegExp instance points to the wrong "this" when executed. That's over-come by using a duck-type compatible this object: the actual RegExp you want to you to test against to set this. Array.filter takes a 2nd argument: this. In short, it takes 2 RegExps to get this to work, but it's still very quick.

If you make a RegExp ahead of time, you don't have the cool one-liner aspect of the routine anymore, but you can simplify/shorten the call somewhat:

Code:
var rx=/e/;
words.filter( rx.test, tx );

bonus
[].filter() and [].map() are powerful, and fast and simple when used with native methods. you may have noticed the empty array slot at the end of words. from the "all words" demo. If that's a problem, filter it out with another native:
Code:
var words=text.split(/[\s,.]+/).filter(String);
Boolean and String are both great [].filter() arguments

Number is great for strong-typing numerical arrays with map(), or removing non-numbers with filter():

Code:
"1,2,3,4,5".split(",").map(Number); //==[1,2,3,4,5]
"1,a,3,b,5".split(",").filter(Number);//==["1","3","5"]
"1,a,3,b,5".split(",").filter(Number).map(Number);//==[1,3,5]
if you need to support older IE versions, you can makes sure [].map is available with code from MDN, use the underscore lib, http://danml.com/f/, or many other libraries.


here is [].map, [].filter, [].reduce, and all the other "Array 1.6" methods in under 1kb:
Code:
eval(function (s,r){var a,x,i=0,m=r.length,q=/([.*+?^${}()|[\]\/\\])/g;for(;i<m;i++){a=r[i]||"";x=RegExp(a.slice(0,1).replace(q,"\\$1"),"g");s=s.replace(x,a.slice(1))}return s}("(&n(#var o=Array.prototype,H,i,e={map/i=0,r=[]BVr[i]8G,V}Nr9J<0Bt@a.3(G,V#r[g++Kt[i]MNr9every/i=0;Nm@t.JU.length==m9some/i=1;Q(;mT;#P@a.3(tDmCm,V@!Ti#$!0}}$!19lastIndexOf/i=b6-1;Q(;m>i;mT#P@t[mK==a#Nl}}$-194dexOf/i=b60Bt@t[iK==a#Ni}}$-19reduce/i=0,r=b6t[i++]L57r8nul*reduceRight/i=m-1,r=b6t[iT]%>-1;iT#r8nul*QEach:&n(a,b#this.concat().mapU9clean<0,x,O;a=Function(a6Str4g)Bt@(x8G,V)#r[g++KxMNarguments[2]?b:rMQ(H 4 e#i=o[H];o[HKi6e[H]}}());","Vt)`U(a,b)`T--`BT4 `TLB `Pif(m 4 t`N$ `M}};`</i=0,r=[Cg=`L%<`K]=`Jfilter`Hit`GbDiCi`D,t[`C],`6||`B576`Qfor`&functio`@&&`9},`8=a.3(`7++#`6if(i`5m;i`4in`3call`#){`/:#,`*l,r,t[i],i,t)}$ r},`%;for(;i`$return`#functio$length`$n(a,b){var t=#=t.`#this.concat(),m".split('`')));
__________________
my site (updated 5/13)
STATS (2013/5) HTML5:90.2% MOB:14% IE7:0.5% IE8:8.6% IE9:9.8% IE10:10%

Last edited by rnd me; 11-10-2011 at 04:51 PM..
rnd me is online now   Reply With Quote
Users who have thanked rnd me for this post:
Kor (11-21-2011)
Reply

Bookmarks

Tags
array, data, filter, list, map

Jump To Top of Thread


Thread Tools
Rate This Thread
Rate This Thread:

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off

Forum Jump


All times are GMT +1. The time now is 10:46 PM.


Advertisement
Log in to turn off these ads.