<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>unscriptable.com &#187; jQuery</title>
	<atom:link href="http://unscriptable.com/category/javascript/jquery/feed/" rel="self" type="application/rss+xml" />
	<link>http://unscriptable.com</link>
	<description>Just another WordPress site</description>
	<lastBuildDate>Thu, 02 Feb 2012 03:05:33 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.1</generator>
		<item>
		<title>OOCSS for JavaScript Pirates</title>
		<link>http://unscriptable.com/2010/11/15/oocss-for-javascript-pirates/</link>
		<comments>http://unscriptable.com/2010/11/15/oocss-for-javascript-pirates/#comments</comments>
		<pubDate>Tue, 16 Nov 2010 03:17:52 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[CSS]]></category>
		<category><![CDATA[jQuery]]></category>
		<category><![CDATA[Non-programming]]></category>
		<category><![CDATA[OOCSS]]></category>

		<guid isPermaLink="false">http://unscriptable.com/?p=676</guid>
		<description><![CDATA[A few weeks back I had the awesome opportunity to speak at the jQuery Conference in Boston. A colleague, Boaz Sender, encouraged me to propose a topic, but I couldn&#8217;t help wondering, &#8220;What could a dojo enthusiast possibly speak about at a jQuery conference?&#8221; Speak about dojo? Uh, no way. That wouldn&#8217;t fly. How about [...]]]></description>
			<content:encoded><![CDATA[<p>A few weeks back I had the awesome opportunity to speak at the <a href="http://events.jquery.org/2010/boston/">jQuery Conference in Boston</a>.  A colleague, <a href="http://boazsender.com/">Boaz Sender</a>, encouraged me to propose a topic, but I couldn&#8217;t help wondering, &#8220;What could a dojo enthusiast possibly speak about at a jQuery conference?&#8221;  </p>
<p><em>Speak about dojo? Uh, no way. That wouldn&#8217;t fly.</em></p>
<p><em>How about something about pure JavaScript? Maybe I could extract a feature of cujo.js and turn it into a jQuery plugin! &#8230; Nah, that&#8217;ll take too long.  No time.</em></p>
<p><em>Wait! OOCSS! It&#8217;s applicable to all JavaScript development!</em><br />
<span id="more-676"></span></p>
<p><!-- embedded slideshare widget --></p>
<div style="width:425px; float:right; margin-left: 10px;" id="__ss_5465648"><strong style="display:block;margin:12px 0 4px"><a href="http://www.slideshare.net/unscriptable/oocss-for-javascript-pirates-jqcon-boston" title="OOCSS for JavaScript Pirates jQcon Boston">OOCSS for JavaScript Pirates jQcon Boston</a></strong><object id="__sse5465648" width="425" height="355"><param name="movie" value="http://static.slidesharecdn.com/swf/ssplayer2.swf?doc=oocssforjavascriptpiratespresentationatjqconboston-101017095722-phpapp01&#038;rel=0&#038;stripped_title=oocss-for-javascript-pirates-jqcon-boston&#038;userName=unscriptable" /><param name="allowFullScreen" value="true"/><param name="allowScriptAccess" value="always"/><embed name="__sse5465648" src="http://static.slidesharecdn.com/swf/ssplayer2.swf?doc=oocssforjavascriptpiratespresentationatjqconboston-101017095722-phpapp01&#038;rel=0&#038;stripped_title=oocss-for-javascript-pirates-jqcon-boston&#038;userName=unscriptable" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="425" height="355"></embed></object>
<div style="padding:5px 0 12px">View more <a href="http://www.slideshare.net/">presentations</a> from <a href="http://www.slideshare.net/unscriptable">John Hann</a>.</div>
</div>
<p>I knew that topic was the best chance I had &#8212; if a dojo guy had a chance at all &#8212; to speak at a jQuery conference.  But how to sell the idea to jQuery developers?  Most of the JavaScript coders I know either don&#8217;t understand CSS or don&#8217;t care to understand it.  Well, to be fair, that description fits most of the dojo coders I know.  Lots of jQuery devs come from a design background, so they know CSS.  But still&#8230; how to let the conference attendees know that this talk won&#8217;t simply be about the same old CSS concepts?</p>
<p><em>I&#8217;ll have to just tell them it&#8217;s for advanced coders! This is <strong>CSS for JavaScript Pirates!!!</strong></em></p>
<p>There were only a few days left before I had to submit the proposal for the talk, so I did what every over-worked coder does: I waited until the night the proposal was due.  </p>
<p>I did two revisions before calling it good enough.  (I usually like to wait a few days between revisions because it makes it easier for me to judge the content objectively, but that almost never happens.)</p>
<p>At the bottom of my proposal, I added some additional notes:</p>
<blockquote><p>Note to reviewer: It&#8217;s no secret that I&#8217;m a dojo contributor working on a dojo-based MVC framework (cujo.js).  Let it be known that I&#8217;ve also worked on my share of jQuery projects!  (Who hasn&#8217;t?)  This talk is about OOCSS and JavaScript, not cujo.js or dojo.  I will be showing jQuery code snippets and will explain techniques that jQuery devs can use in their current projects.
</p></blockquote>
<p><em>That oughta alleviate any doubters.  I hope.</em></p>
<p>There was still one major problem, though.  I needed a demo.  I could show some code snippets on the screen, but without a real demo, it just wouldn&#8217;t have the same impact.  I thought I&#8217;d have to write one.  But I knew I&#8217;d never make the time and would end up rushing both the presentation and the demo.  That&#8217;d just make for a sucky experience &#8212; and a sucky, stressful week.</p>
<p>Then it dawned on me.  My buddy, <a href="http://blog.briancavalier.com/">Brian</a>, had an awesome demo already!  His <a href="http://briancavalier.com/digital-clock/">CSS3 Digital Clock</a> app would be perfect!  </p>
<p><em>First, let&#8217;s see if I even get picked. </em></p>
<p>Two days later I got the email with the subject line: &#8220;Your jQuery Boston Conference 2010 talk is accepted!&#8221;</p>
<p><em><strong>WOOHOO!!!</strong></em></p>
<p>A couple of emails, chat conversations, and phone calls later Brian was on the speaker list, too!  </p>
<p><em>This is gonna be EPIC!</em></p>
<p>And it was.  I got a bit nervous in the middle and forgot half of what I wanted to say, but I think I got the major points across.  Brian did an amazing demo, and several dozens of people came up to us later and thanked us for the talk.  I guess that means it was a success.  </p>
<p>Kudos to the jQuery team, to the conference organizers, and to the other speakers.  The whole conference was a huge success, imho.  I am quite honored to have been able to participate in such an awesome event.</p>
<p>For more about the presentation and OOCSS, check out some of these links:</p>
<p>Brian debuted the <a href="http://briancavalier.com/digital-clock/explode.html">exploding mod</a> of the digital clock at the show.  (Very cool.)</p>
<p>Brian&#8217;s <a href="http://blog.briancavalier.com/oocss-for-javascript-pirates-at-jqcon-2010">write-up</a> after the event.</p>
<p>Brian, looking more like a <a href="http://photos.brookhartfamily.com/Events/jQuery-Conference-Boston-2010/14226246_2VpfJ#1051103962_WwDrN">GQ model</a>, than a pirate.  </p>
<p>Me, looking <a href="http://photos.brookhartfamily.com/Events/jQuery-Conference-Boston-2010/14226246_2VpfJ#1051103183_kUhYa">rather stressed</a>. I think I was saying &#8220;yarrrrrrrr&#8221;.</p>
<p>Another link to the <a href="http://www.slideshare.net/unscriptable/oocss-for-javascript-pirates-jqcon-boston">slides</a>.</p>
<p><a href="http://speakerrate.com/talks/4642-oocss-for-javascript-pirates">Rate me and Brian</a> if you attended the talk!</p>
<p>The <a href="http://wiki.github.com/stubbornella/oocss/">github repo</a> for OOCSS.</p>
]]></content:encoded>
			<wfw:commentRss>http://unscriptable.com/2010/11/15/oocss-for-javascript-pirates/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Deduplicate any array in Javascript</title>
		<link>http://unscriptable.com/2009/12/08/deduplicate-any-array-in-javascript/</link>
		<comments>http://unscriptable.com/2009/12/08/deduplicate-any-array-in-javascript/#comments</comments>
		<pubDate>Tue, 08 Dec 2009 05:04:30 +0000</pubDate>
		<dc:creator>John Hann</dc:creator>
				<category><![CDATA[dojo]]></category>
		<category><![CDATA[Javascript]]></category>
		<category><![CDATA[jQuery]]></category>
		<category><![CDATA[performance]]></category>

		<guid isPermaLink="false">http://unscriptable.com/?p=467</guid>
		<description><![CDATA[As part of an ongoing project, I had to deduplicate a potentially large array of nodes.  ...  It seemed every other implementation used the hash map method and only worked on limited data types.  I hate writing the same code twice (unless it's to improve it), so I decided to write something that works with any data type.]]></description>
			<content:encoded><![CDATA[<p>I&#8217;ve neglected this blog lately.  My only excuse is that I am <em>very, very busy</em>! Not only have I been lucky enough to land a great opportunity working with some very bright jQuery Interactive Developers at <a href="http://www.molecular.com/">Molecular</a>, but I&#8217;ve also been working on <strong>something really big</strong>.  (More on that later!)</p>
<p>But despite being busy, I felt compelled to post this one. As part of the <strong>something really big</strong> project, I had to <a href="http://en.wikipedia.org/wiki/Data_deduplication">deduplicate</a> a potentially large array of nodes.  Dojo doesn&#8217;t have a built-in function for deduplication (a.k.a &#8220;deduping&#8221;).  How could it not?  Doesn&#8217;t everybody have to do this once in a while?  </p>
<p><em>I guess I&#8217;ll have to write one.  How hard could it be?</em><br />
<span id="more-467"></span><br />
It wasn&#8217;t because dojo didn&#8217;t implement a deduping method that I felt compelled.  No, it was the series of events after I wrote my own version.  Just after I finished it, one of those smart IDevs at Molecular shared his recent hash map-based implementations that worked only with numbers.  Then I noticed that jQuery has a deduping method, <code>unique()</code>.  However, it only deduplicates DOM Nodes.  </p>
<p>Finally, I ran across this blog <a href="http://dreaminginjavascript.wordpress.com/2008/08/22/eliminating-duplicates">post</a> that uses the hash-map method and works only on strings.  (Actually, it works on any objects that return unique values from their toString() methods, but that&#8217;s not as common as you&#8217;d think in Javascript. For example, object literals typically return &#8220;[Object object]&#8221; from the toString() method.)</p>
<p>It seemed every other implementation used the hash map method and only worked on limited data types.  I hate writing the same code twice (unless it&#8217;s to improve it), so I decided to write something that works with any data type.  </p>
<p><strong><em>One function to rule them all!</em> (No! Don&#8217;t even go there&#8230;!)</strong></p>
<p>I probably should have done some research before diving in, but that&#8217;s not how I roll.  (Where&#8217;s the challenge in that?)  From previous experience I already knew of at least two ways to do it: a) keeping a hash map of the values (hash map method), or b) pre-sorting the values.  The former method (hash map) seemed slower and more memory intensive, so I forged ahead with the second method (pre-sorting).</p>
<p>The pre-sort method works like this:</p>
<ol>
<li>sort the data items in the array</li>
<li>loop through the sorted data items:</li>
<li>compare each of the data items to the previous one</li>
<li>if the previous is the same as the current, don&#8217;t add the current item to the output array</li>
</ol>
<p><em>Simple enough!</em></p>
<p>Here&#8217;s the code using dojo to wrap the Javascript 1.6 Array iterators:</p>

<div class="wp_syntax"><div class="code"><pre class="javascript" style="font-family:monospace;">    <span style="color: #003366; font-weight: bold;">function</span> dedup <span style="color: #009900;">&#40;</span><span style="color: #009966; font-style: italic;">/* Array */</span> array<span style="color: #339933;">,</span> <span style="color: #009966; font-style: italic;">/* Function */</span> compareFunc<span style="color: #339933;">,</span> <span style="color: #009966; font-style: italic;">/* Object? */</span> context<span style="color: #339933;">,</span> <span style="color: #009966; font-style: italic;">/* Boolean? */</span> preemptive<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
        <span style="color: #006600; font-style: italic;">//  summary: removes duplicate items from an array. compareFunc should behave</span>
        <span style="color: #006600; font-style: italic;">//      exactly like the lambda function used in array.sort(), returning:</span>
        <span style="color: #006600; font-style: italic;">//       0 - if the two items to compare are equivalent</span>
        <span style="color: #006600; font-style: italic;">//      -1 - if the first item should be sorted to an earlier position than the second</span>
        <span style="color: #006600; font-style: italic;">//       1 - if the first item should be sorted to a later position than the second</span>
        <span style="color: #006600; font-style: italic;">//      Returns an array with no duplicates.</span>
        <span style="color: #006600; font-style: italic;">//      Note: items found later in the array are favored over earlier items. This means</span>
        <span style="color: #006600; font-style: italic;">//      that if am earlier item is found to be a duplicate of an later item, it is not</span>
        <span style="color: #006600; font-style: italic;">//      included in the returned array.  You might ask, &quot;Who cares which one is favored?&quot;</span>
        <span style="color: #006600; font-style: italic;">//      Glad you asked! It depends upon how you define &quot;duplicate&quot;. If you wanted to</span>
        <span style="color: #006600; font-style: italic;">//      remove all nodes with duplicate ids, you could supply a compareFunc that inspected</span>
        <span style="color: #006600; font-style: italic;">//      node ids.  The nodes are not identical in this case, just the ids.</span>
        <span style="color: #006600; font-style: italic;">//      If you wish to favor the earlier items, set preemptive = true;</span>
        <span style="color: #006600; font-style: italic;">//      Note: undefined values are omitted from the output array.</span>
        <span style="color: #006600; font-style: italic;">//  array: Array - the array to be deduped</span>
        <span style="color: #006600; font-style: italic;">//  compareFunc: Function - see above</span>
        <span style="color: #006600; font-style: italic;">//  context: Object - context on which to run compareFunc (i.e. the &quot;this&quot; reference from</span>
        <span style="color: #006600; font-style: italic;">//      within compareFunc). defaults to null/window</span>
        <span style="color: #006600; font-style: italic;">//  preemptive: Boolean - set to true to favor earlier occuring items (see above)</span>
        <span style="color: #003366; font-weight: bold;">var</span> comparator <span style="color: #339933;">=</span> <span style="color: #003366; font-weight: bold;">function</span> <span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span> <span style="color: #000066; font-weight: bold;">return</span> compareFunc.<span style="color: #660066;">apply</span><span style="color: #009900;">&#40;</span>context<span style="color: #339933;">,</span> arguments<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> <span style="color: #009900;">&#125;</span><span style="color: #339933;">,</span>
            prev<span style="color: #339933;">,</span>
            keepers <span style="color: #339933;">=</span> <span style="color: #009900;">&#91;</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span>
        <span style="color: #006600; font-style: italic;">// by first sorting the array, we know that dups will be adjacent to each other</span>
        dojo.<span style="color: #660066;">forEach</span><span style="color: #009900;">&#40;</span>array.<span style="color: #660066;">sort</span><span style="color: #009900;">&#40;</span>comparator<span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span> <span style="color: #003366; font-weight: bold;">function</span> <span style="color: #009900;">&#40;</span><span style="color: #000066; font-weight: bold;">item</span><span style="color: #339933;">,</span> pos<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
            <span style="color: #000066; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #000066; font-weight: bold;">typeof</span> <span style="color: #000066; font-weight: bold;">item</span> <span style="color: #339933;">!=</span> <span style="color: #3366CC;">'undefined'</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
                <span style="color: #000066; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #000066; font-weight: bold;">typeof</span> prev <span style="color: #339933;">==</span> <span style="color: #3366CC;">'undefined'</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
                    keepers.<span style="color: #660066;">push</span><span style="color: #009900;">&#40;</span>pos<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
                <span style="color: #009900;">&#125;</span>
                <span style="color: #000066; font-weight: bold;">else</span> <span style="color: #009900;">&#123;</span>
                    <span style="color: #006600; font-style: italic;">// is the previous item different from this one?</span>
                    <span style="color: #003366; font-weight: bold;">var</span> eq <span style="color: #339933;">=</span> comparator<span style="color: #009900;">&#40;</span>prev<span style="color: #339933;">,</span> <span style="color: #000066; font-weight: bold;">item</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">==</span> <span style="color: #CC0000;">0</span><span style="color: #339933;">;</span>
                    <span style="color: #000066; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span>preemptive<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
                        <span style="color: #000066; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #339933;">!</span>eq<span style="color: #009900;">&#41;</span>
                            keepers.<span style="color: #660066;">push</span><span style="color: #009900;">&#40;</span>pos<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> <span style="color: #006600; font-style: italic;">// add this one</span>
                    <span style="color: #009900;">&#125;</span>
                    <span style="color: #000066; font-weight: bold;">else</span> <span style="color: #009900;">&#123;</span>
                        <span style="color: #000066; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span>eq<span style="color: #009900;">&#41;</span>
                            keepers.<span style="color: #660066;">pop</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> <span style="color: #006600; font-style: italic;">// remove prev one</span>
                        keepers.<span style="color: #660066;">push</span><span style="color: #009900;">&#40;</span>pos<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> <span style="color: #006600; font-style: italic;">// always add current one (it may be deleted in the next iteration)</span>
                    <span style="color: #009900;">&#125;</span>
                <span style="color: #009900;">&#125;</span>
                prev <span style="color: #339933;">=</span> <span style="color: #000066; font-weight: bold;">item</span><span style="color: #339933;">;</span>
            <span style="color: #009900;">&#125;</span>
        <span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #000066; font-weight: bold;">return</span> dojo.<span style="color: #660066;">map</span><span style="color: #009900;">&#40;</span>keepers<span style="color: #339933;">,</span> <span style="color: #003366; font-weight: bold;">function</span> <span style="color: #009900;">&#40;</span>pos<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span> <span style="color: #000066; font-weight: bold;">return</span> array<span style="color: #009900;">&#91;</span>pos<span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span> <span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span></pre></div></div>

<p>The dedup() method requires an array (duh) and a comparison function (compareFunc).  The comparison function is exactly the same function you&#8217;d pass to sort an array.  Note that it&#8217;s run twice: once to sort the array and once to test if the previous value is the same as the current value.</p>
<p>The context parameter is useful if you need to pull in other data for compareFunc to do its job in the context of some object.  For even more control over which duplicate instances are kept, you can use the preemptive parameter.  Set this to true to keep items that occur earlier in the array.</p>
<p>I can see some people scratching their heads. <em>Why does it matter which item we keep if they&#8217;re duplicates of each other?</em>  Well, nobody said they had to be <em>exact</em> duplicates!  For instance, maybe you want to reduce a table&#8217;s rows to only the ones that have unique integer values in their first cell.</p>
<p>And here&#8217;s how you&#8217;d do that (error-checking omitted for brevity):</p>

<div class="wp_syntax"><div class="code"><pre class="javascript" style="font-family:monospace;"><span style="color: #003366; font-weight: bold;">var</span> myDedupedRows <span style="color: #339933;">=</span> dedup<span style="color: #009900;">&#40;</span>myTable.<span style="color: #660066;">rows</span><span style="color: #339933;">,</span> <span style="color: #003366; font-weight: bold;">function</span> <span style="color: #009900;">&#40;</span>rowA<span style="color: #339933;">,</span> rowB<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
    <span style="color: #006600; font-style: italic;">// it's important to use a comparison that works correctly in Array sort() for best efficiency!</span>
    <span style="color: #000066; font-weight: bold;">return</span> parseInt<span style="color: #009900;">&#40;</span>rowA.<span style="color: #660066;">cells</span><span style="color: #009900;">&#91;</span><span style="color: #CC0000;">0</span><span style="color: #009900;">&#93;</span>.<span style="color: #660066;">innerHTML</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">-</span> parseInt<span style="color: #009900;">&#40;</span>rowB.<span style="color: #660066;">cells</span><span style="color: #009900;">&#91;</span><span style="color: #CC0000;">0</span><span style="color: #009900;">&#93;</span>.<span style="color: #660066;">innerHTML</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></div></div>

<p>That&#8217;s pretty simple if you are already comfortable with writing lambda functions for the sort method, of course.</p>
<p>Deduping numbers:</p>

<div class="wp_syntax"><div class="code"><pre class="javascript" style="font-family:monospace;"><span style="color: #003366; font-weight: bold;">var</span> uniques <span style="color: #339933;">=</span> dedup<span style="color: #009900;">&#40;</span>arrayOfNumberIDs<span style="color: #339933;">,</span> <span style="color: #003366; font-weight: bold;">function</span> <span style="color: #009900;">&#40;</span>idA<span style="color: #339933;">,</span> idB<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
    <span style="color: #000066; font-weight: bold;">return</span> idA <span style="color: #339933;">-</span> idB<span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></div></div>

<p>Deduping object instances:</p>

<div class="wp_syntax"><div class="code"><pre class="javascript" style="font-family:monospace;"><span style="color: #003366; font-weight: bold;">var</span> uniques <span style="color: #339933;">=</span> dedup<span style="color: #009900;">&#40;</span>myObjects<span style="color: #339933;">,</span> <span style="color: #003366; font-weight: bold;">function</span> <span style="color: #009900;">&#40;</span>objA<span style="color: #339933;">,</span> objB<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
    <span style="color: #006600; font-style: italic;">// this works for numbers, strings, dates... but don't mix types!</span>
    <span style="color: #000066; font-weight: bold;">return</span> objA.<span style="color: #660066;">keyProperty</span> <span style="color: #339933;">-</span> objB.<span style="color: #660066;">keyProperty</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></div></div>

<p>Deduping object instances that have multiple key properties:</p>

<div class="wp_syntax"><div class="code"><pre class="javascript" style="font-family:monospace;"><span style="color: #003366; font-weight: bold;">var</span> uniques <span style="color: #339933;">=</span> dedup<span style="color: #009900;">&#40;</span>myObjects<span style="color: #339933;">,</span> <span style="color: #003366; font-weight: bold;">function</span> <span style="color: #009900;">&#40;</span>objA<span style="color: #339933;">,</span> objB<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
    <span style="color: #003366; font-weight: bold;">var</span> test <span style="color: #339933;">=</span> objA.<span style="color: #660066;">keyProperty</span> <span style="color: #339933;">-</span> objB.<span style="color: #660066;">keyProperty</span><span style="color: #339933;">;</span>
    <span style="color: #000066; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span>test <span style="color: #339933;">==</span> <span style="color: #CC0000;">0</span><span style="color: #009900;">&#41;</span> <span style="color: #006600; font-style: italic;">// keyProperty is the same, so dig deeper</span>
        <span style="color: #000066; font-weight: bold;">return</span> objA.<span style="color: #660066;">altKey</span> <span style="color: #339933;">-</span> objB.<span style="color: #660066;">altKey</span><span style="color: #339933;">;</span>
    <span style="color: #000066; font-weight: bold;">else</span>
        <span style="color: #000066; font-weight: bold;">return</span> test<span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></div></div>

<p>Deduping numbers the safe way:</p>

<div class="wp_syntax"><div class="code"><pre class="javascript" style="font-family:monospace;"><span style="color: #003366; font-weight: bold;">var</span> uniques <span style="color: #339933;">=</span> dedup<span style="color: #009900;">&#40;</span>arrayOfNumberIDs<span style="color: #339933;">,</span> <span style="color: #003366; font-weight: bold;">function</span> <span style="color: #009900;">&#40;</span>idA<span style="color: #339933;">,</span> idB<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
    <span style="color: #006600; font-style: italic;">// force to numbers in case we have strings by accident</span>
    <span style="color: #000066; font-weight: bold;">return</span> parseFloat<span style="color: #009900;">&#40;</span>idA<span style="color: #009900;">&#41;</span> <span style="color: #339933;">-</span> parseFloat<span style="color: #009900;">&#40;</span>idB<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></div></div>

<p>At first glance, the pre-sort method looks more complex than the hash map methods, but it&#8217;s really not.  Once you take out the code that skips undefined values (like all good <a href="https://developer.mozilla.org/en/New_in_JavaScript_1.6">array iterators</a> should) and the code to allow the preemptive functionality, it&#8217;s only a line or two longer.</p>
<p>How about memory usage?  Hm.  My assumption that my method would use less memory wasn&#8217;t as accurate as I thought.  In the hash map methods, a temporary array and a hash-map of the non-redundant values are created.  In my pre-sort method, a complete copy of the original array and a copy of the deduped array are created.  This could go either way, depending on how large the original array is and on how Javascript engines internally manage hash maps (object literals, actually), but it&#8217;s likely that the pre-sort has a larger memory footprint.  (It&#8217;s likely that the Javascript engines create internal data structures to speed-up property look-ups on object literals.  However, it&#8217;s certain that the engines pre-allocate several kilobytes of space for array items. I&#8217;ll bet they allocate a minimum of 16kB per array created.)</p>
<p>Finally, I&#8217;m hesitant to claim any performance prizes, either.  I assume that since the compareFunc is run at least twice for each item in the array, it&#8217;s a performance bottleneck.  The hash map methods don&#8217;t do much in Javascript besides the loops.  The rest is run inside compiled code under the hood of the Javascript engine.  </p>
<p><strong>But maybe that&#8217;s the price for creating a function that dedups anything?</strong></p>
<p>I&#8217;m too <del datetime="2009-12-08T03:53:13+00:00">lazy</del> busy to test any of my assumptions, but if you are intrigued or bored, please have at it!  </p>
<p>And be sure to post any feedback! Did I miss something?  Did I make a stoopid mistake?   Can you write a version that falls back to the hash map method when using simple data types (and therefore doesn&#8217;t need compareFunc)?  </p>
<p>What? You don&#8217;t use dojo?!?! <img src='http://unscriptable.com/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' />   A jQuery port should be brain-dead simple (s/dojo.forEach/$.each/ and s/dojo.map/$.map/).  Here&#8217;s a version that replaces the dojo calls with Javascript 1.6 array iterators.   (Note: Javascript 1.6 array iterators work in recent browsers only!)</p>

<div class="wp_syntax"><div class="code"><pre class="javascript" style="font-family:monospace;">    <span style="color: #003366; font-weight: bold;">function</span> dedup <span style="color: #009900;">&#40;</span>array<span style="color: #339933;">,</span> compareFunc<span style="color: #339933;">,</span> context<span style="color: #339933;">,</span> preemptive<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
        <span style="color: #003366; font-weight: bold;">var</span> comparator <span style="color: #339933;">=</span> <span style="color: #003366; font-weight: bold;">function</span> <span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span> <span style="color: #000066; font-weight: bold;">return</span> compareFunc.<span style="color: #660066;">apply</span><span style="color: #009900;">&#40;</span>context<span style="color: #339933;">,</span> arguments<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> <span style="color: #009900;">&#125;</span><span style="color: #339933;">,</span>
            prev<span style="color: #339933;">,</span>
            keepers <span style="color: #339933;">=</span> <span style="color: #009900;">&#91;</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span>
        array.<span style="color: #660066;">sort</span><span style="color: #009900;">&#40;</span>comparator<span style="color: #009900;">&#41;</span>.<span style="color: #660066;">forEach</span><span style="color: #009900;">&#40;</span><span style="color: #003366; font-weight: bold;">function</span> <span style="color: #009900;">&#40;</span><span style="color: #000066; font-weight: bold;">item</span><span style="color: #339933;">,</span> pos<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
            <span style="color: #000066; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #000066; font-weight: bold;">typeof</span> <span style="color: #000066; font-weight: bold;">item</span> <span style="color: #339933;">!=</span> <span style="color: #3366CC;">'undefined'</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
                <span style="color: #000066; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #000066; font-weight: bold;">typeof</span> prev <span style="color: #339933;">==</span> <span style="color: #3366CC;">'undefined'</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
                    keepers.<span style="color: #660066;">push</span><span style="color: #009900;">&#40;</span>pos<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
                <span style="color: #009900;">&#125;</span>
                <span style="color: #000066; font-weight: bold;">else</span> <span style="color: #009900;">&#123;</span>
                    <span style="color: #003366; font-weight: bold;">var</span> eq <span style="color: #339933;">=</span> comparator<span style="color: #009900;">&#40;</span>prev<span style="color: #339933;">,</span> <span style="color: #000066; font-weight: bold;">item</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">==</span> <span style="color: #CC0000;">0</span><span style="color: #339933;">;</span>
                    <span style="color: #000066; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span>preemptive<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
                        <span style="color: #000066; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #339933;">!</span>eq<span style="color: #009900;">&#41;</span>
                            keepers.<span style="color: #660066;">push</span><span style="color: #009900;">&#40;</span>pos<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
                    <span style="color: #009900;">&#125;</span>
                    <span style="color: #000066; font-weight: bold;">else</span> <span style="color: #009900;">&#123;</span>
                        <span style="color: #000066; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span>eq<span style="color: #009900;">&#41;</span>
                            keepers.<span style="color: #660066;">pop</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
                        keepers.<span style="color: #660066;">push</span><span style="color: #009900;">&#40;</span>pos<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
                    <span style="color: #009900;">&#125;</span>
                <span style="color: #009900;">&#125;</span>
                prev <span style="color: #339933;">=</span> <span style="color: #000066; font-weight: bold;">item</span><span style="color: #339933;">;</span>
            <span style="color: #009900;">&#125;</span>
        <span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #000066; font-weight: bold;">return</span> keepers.<span style="color: #660066;">map</span><span style="color: #009900;">&#40;</span><span style="color: #003366; font-weight: bold;">function</span> <span style="color: #009900;">&#40;</span>pos<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span> <span style="color: #000066; font-weight: bold;">return</span> array<span style="color: #009900;">&#91;</span>pos<span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span> <span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span></pre></div></div>

]]></content:encoded>
			<wfw:commentRss>http://unscriptable.com/2009/12/08/deduplicate-any-array-in-javascript/feed/</wfw:commentRss>
		<slash:comments>8</slash:comments>
		</item>
	</channel>
</rss>

