Bitovi take-home exercise
by ryanwheale
HTML
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/3.9.3/lodash.min.js"></script>
<h1>Bitovi take home exercise</h1>
<p>Using <q>whatever resources you want</q> I have created several different techniques for making an array unique. The scope of this exercise only required the handling of objects, which was my first prerogative. However, creating a utility method like this should be able to handle any type of data <abbr title="in my opinion">IMO</abbr>.</p>
<p>In day-to-day work I would lean on existing utilities like lodash to handle things like this - so that was my first attempt </too_easy>. The next two attempts reflect what I might write on some Tuesday without a utility library. Items marked in <em class="inaccurate">red</em> highlight techniques which do not result in an array of truly unique values (due to <code>NaN</code>). The last attempt is a bit overboard but the result of what happens when I get into a battle with a stopwatch.</p>
<p>After it was all said and done, I wanted to know how the lodash guys got it so fast - and they are leveraging ES6 <code>Set</code> - which brings me back to my intial inclination to use a utility library for these types of things. Did I learn a lot in this exercise: <strong>yes</strong>. I even <a href="http://jsfiddle.net/ryanwheale/ohe9gzxd/3/" target="_top">tried my hand at the <code>Set</code> technique</a> with some rather pleasing results</p>
CSS
h2 {
background-color: #345;
color: #fed;
padding: .3em;
}
code {
background-color: #eee;
padding: 0 .3em;
}
table {
width: 100%;
}
.inaccurate {
color: red;
}
JavaScript
var count = 15000,
generatePrimitives = false,
primitiveValues = [null, undefined, NaN],
val, i, tests;
// add some ints & strings
for (i = 48; i < 70; i++) {
val = String.fromCharCode(i);
primitiveValues.push(i < 58 ? parseInt(val, 10) : val);
}
function _random (max) {
return Math.floor(Math.random() * max);
}
function generateData () {
var arr = [],
i = count,
primVals = primitiveValues.slice(),
n, item;
while (i--) {
if (generatePrimitives && primVals.length) {
item = primVals.pop();
} else {
item = {};
for (n = 0; n < 5; n++) {
item["prop_" + n] = Math.random();
}
}
arr.push(item);
}
while (i++ < count/2) {
if (generatePrimitives && Math.random() < 0.5) {
item = primitiveValues[_random(primitiveValues.length)];
} else {
item = arr[i];
}
arr.splice(_random(count), 0, item);
}
return arr;
}
tests = [{
title: "Lodash",
fn: _.uniq
}, {
title: "Array.prototype.indexOf",
fn: function (arr) {
var uniqs = [], i = -1, l = arr.length, item;
while (++i < l) {
item = arr[i];
if (uniqs.indexOf(item) === -1) {
uniqs.push(item);
}
}
return uniqs;
}
}, {
title: "Nested Loop",
maxOut: 15000,
fn: function (arr) {
var uniqs = [],
count = 0, i = -1, l = arr.length, item, n, nl;
while(++i < l) {
item = arr[i];
for (n = 0, nl = count; n < nl; n++) {
if (uniqs[n] === item) {
break;
}
}
if (n === count) {
uniqs.push(item);
count++;
}
}
return uniqs;
}
}, {
title: "Custom technique",
fn:...