Created
July 11, 2012 10:12
-
-
Save bobrik/3089440 to your computer and use it in GitHub Desktop.
lodash objectDifference implementation and benchmark code
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
(function(module) { | |
var Benchmark = require('../vendor/benchmark.js/benchmark.js'), | |
_ = require('../vendor/underscore/underscore.js'), | |
lodash = require('../lodash.js'); | |
var numbers = [], | |
fourNumbers = [5, 25, 10, 30], | |
twoNumbers = [12, 21], | |
i; | |
for (i = 0; i < 1000; i++) { | |
numbers.push(Math.round(Math.random() * 10000)); | |
} | |
for (i = 0; i < 1000; i++) { | |
fourNumbers.push(Math.round(Math.random() * 10000)); | |
} | |
for (i = 0; i < 1000; i++) { | |
twoNumbers.push(Math.round(Math.random() * 10000)); | |
} | |
function test(numbers, twoNumbers, fourNumbers) { | |
console.log("array sizes: ", numbers.length, twoNumbers.length, fourNumbers.length); | |
console.log("lodash is equal to underscore:", JSON.stringify(lodash.difference(numbers, fourNumbers, twoNumbers)) == JSON.stringify(_.difference(numbers, fourNumbers, twoNumbers))); | |
console.log("lodash is equal to object method:", JSON.stringify(lodash.difference(numbers, fourNumbers, twoNumbers)) == JSON.stringify(lodash.objectDifference(numbers, fourNumbers, twoNumbers))); | |
console.log("difference size:", lodash.difference(numbers, fourNumbers, twoNumbers).length); | |
Benchmark.Suite('`_.difference`') | |
.add('Lo-Dash', function() { | |
lodash.difference(numbers, fourNumbers, twoNumbers); | |
}) | |
.add('Underscore', function() { | |
_.difference(numbers, fourNumbers, twoNumbers); | |
}) | |
.add('Objects', function() { | |
lodash.objectDifference(numbers, fourNumbers, twoNumbers); | |
}) | |
.on('cycle', function(event) { | |
console.log(String(event.target)); | |
}) | |
.on('complete', function() { | |
console.log('Fastest is ' + this.filter('fastest').pluck('name')) | |
}).run({async: false}); | |
} | |
function testWithSizes(first, second, third, max) { | |
var numbers = [], | |
twoNumbers = [], | |
fourNumbers = [], | |
i; | |
for (i = 0; i < first; i++) { | |
numbers.push(Math.round(Math.random() * max)); | |
} | |
for (i = 0; i < second; i++) { | |
twoNumbers.push(Math.round(Math.random() * max)); | |
} | |
for (i = 0; i < third; i++) { | |
fourNumbers.push(Math.round(Math.random() * max)); | |
} | |
test(numbers, twoNumbers, fourNumbers); | |
} | |
console.log("=== testing simple ==="); | |
test([], [5, 25, 10, 30], [12, 21]); | |
console.log("=== testing 10 ==="); | |
testWithSizes(10, 10, 10, 50); | |
console.log("=== testing 100 ==="); | |
testWithSizes(100, 100, 100, 200); | |
console.log("=== testing 1k ==="); | |
testWithSizes(1000, 1000, 1000, 10000); | |
console.log("=== testing 10k ==="); | |
testWithSizes(10000, 10000, 10000, 10000); | |
console.log("=== testing 100k ==="); | |
testWithSizes(100000, 100000, 100000, 300000); | |
})(module); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# to be used as lodash method | |
function objectDifference(array) { | |
var result = []; | |
if (!array) { | |
return result; | |
} | |
var index = -1, | |
length = array.length, | |
flattened = concat.apply(result, Array.prototype.slice.call(arguments, 1)), | |
obj = {}; | |
forEach(flattened, function(value, index) { | |
obj[value] = value; | |
}); | |
while (++index < length) { | |
if (obj[array[index]] !== array[index]) { | |
result.push(array[index]); | |
} | |
} | |
return result; | |
} |
This fixes it
function objectDifference(array) {
var result = [];
if (!array) {
return result;
}
var value,
flattened = concat.apply(result, arguments),
arrayLength = array.length,
index = arrayLength - 1,
length = flattened.length,
obj = {};
while (++index < length) {
value = flattened[index];
(obj[value] || (obj[value] = [])).push(value);
}
index = -1;
while (++index < arrayLength) {
value = array[index];
if (!obj[value] || indexOf(obj[value], value) < 0) {
result.push(value);
}
}
return result;
}
I'll look into this more after the v0.4.0 bump.
Sounds good! I was thinking about that solution too.
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
this will fail with: