Last active
January 27, 2016 04:41
-
-
Save zaparker/10405078 to your computer and use it in GitHub Desktop.
Based on the LINQ extensions for C# IEnumerables, these functions extend the base JavaScript Array object with new methods for chaining together array operations. Also includes some examples and tests.
This file contains hidden or 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
// performs the specified action on each item in the array | |
Array.prototype.forEach = function (fnAction) { | |
var l = this.length; | |
for (var i = 0; i < l; ++i) { | |
fnAction(this[i]); | |
} | |
} | |
// returns an array containing the items matching the filter | |
Array.prototype.where = function (fnFilter) { | |
var l = this.length; | |
var result = []; | |
for (var i = 0; i < l; ++i) { | |
if (fnFilter(this[i])) result.push(this[i]); | |
} | |
return result; | |
} | |
// returns an array of transformed objects | |
Array.prototype.select = function (fnTransform) { | |
var l = this.length; | |
var result = []; | |
for (var i = 0; i < l; ++i) { | |
result.push(fnTransform(this[i])); | |
} | |
return result; | |
} | |
// returns true if any item in the array match the check function | |
Array.prototype.any = function (fnCheck) { | |
var l = this.length; | |
for (var i = 0; i < l; ++i) { | |
if (fnCheck(this[i])) return true; | |
} | |
return false; | |
} | |
// returns true if all items in the array match the check function | |
Array.prototype.all = function (fnCheck) { | |
var l = this.length; | |
for (var i = 0; i < l; ++i) { | |
if (!fnCheck(this[i])) return false; | |
} | |
return true; | |
} | |
// returns true if any item in the array match the check function | |
Array.prototype.contains = function (item, fnCompare) { | |
fnCompare = fnCompare || (function(i1, i2) { ;return i1 == i2; }); | |
var l = this.length; | |
for (var i = 0; i < l; ++i) { | |
if (fnCompare(item, this[i])) return true; | |
} | |
return false; | |
} | |
// returns an array of distinct values based on either a direct element comparison or using the value provided by fnKey, if provided | |
Array.prototype.distinct = function(fnKey) { | |
fnKey = fnKey || (function(i) { return i; }); | |
var l = this.length; | |
var result = []; | |
for (var i = 0; i < l; ++i) { | |
if(!result.contains(this[i],function(i1, i2) { return fnKey(i1) == fnKey(i2); } )) result.push(this[i]); | |
} | |
return result; | |
} | |
// returns the first item in the array matching the specified filter | |
Array.prototype.first = function (fnFilter) { | |
var l = this.length; | |
for (var i = 0; i < l; ++i) { | |
if (fnFilter(this[i])) return this[i]; | |
} | |
return null; | |
} | |
// returns the last item in the array matching the specified filter | |
Array.prototype.last = function (fnFilter) { | |
for (var i = this.length - 1; i >= 0; --i) { | |
if (fnFilter(this[i])) return this[i]; | |
} | |
return null; | |
} | |
// returns an array of groups, each one in the form of { key: /* key */, values: /* array of matching items */ } | |
Array.prototype.groupBy = function(fnKey) { | |
var keys = this.select(fnKey).distinct(); | |
var result = []; | |
var l = keys.length; | |
for(var i = 0; i < l; ++i) { | |
var key = keys[i]; | |
result.push({key: key, values: this.where(function(j) { return fnKey(j) == key; })}); | |
} | |
return result; | |
} | |
// same as Array.sort, but it returns the sorted array instead of sorting in place | |
Array.prototype.orderBy = function(fnSortExpression) { | |
var result = this.splice(0, this.length); | |
result.sort(fnSortExpression); | |
return result; | |
} | |
// same as Array.sort with the function reversed, but it returns the sorted array instead of sorting in place | |
Array.prototype.orderByDescending = function(fnSortExpression) { | |
var result = this.splice(0, this.length); | |
result.sort(function(t1, t2) { return fnSortExpression(t1, t2) * -1; }); | |
return result; | |
} | |
// returns the union of the two arrays, with an optional comparison function | |
Array.prototype.union = function(aOther, fnCompare) { | |
fnCompare = fnCompare || (function(i1, i2) { return i1 == i2; }); | |
var result = this.distinct(), aDistinct2 = aOther.distinct(); | |
var i = 0, j = 0, l1 = result.length; l2 = aDistinct2.length, item1 = null, item2 = null, found = false; | |
for(i = 0; i < l2; ++i) { | |
item1 = aDistinct2[i]; | |
if(!result.contains(item1, fnCompare))result.push(item1); | |
} | |
return result; | |
}; | |
// returns the intersection of the two arrays, with an optional comparison function | |
Array.prototype.intersect = function(aOther, fnCompare) { | |
fnCompare = fnCompare || (function(i1, i2) { return i1 == i2; }); | |
var aDistinct1 = this.distinct(), aDistinct2 = aOther.distinct(); | |
var i = 0, j = 0, l1 = aDistinct1.length; l2 = aDistinct2.length, item1 = null, item2 = null; | |
var result = []; | |
for(; i < l1; ++i) { | |
item1 = aDistinct1[i]; | |
for(j = 0; j < l2; ++j) { | |
if(fnCompare(item1, aDistinct2[j])) { | |
result.push(item1); | |
break; | |
} | |
} | |
} | |
return result; | |
}; | |
/* BEGIN TESTS | |
var test = [1, 2, 3, 8, 4, 5, 6, 6, 7, 8, 8, 8, 8, 8, 8, 8, 8]; | |
var test2 = [{ foo: 1, bar: 1 }, {foo: 1, bar: 2}, {foo: 2, bar: 3}, {foo: 2, bar: 4}]; | |
var test3 = [6, 7, 4, 9]; | |
test.where(function (t) { | |
return t % 2 == 0; | |
}).select(function (t) { | |
return t + 7; | |
}).forEach(function (t) { | |
alert(t); | |
}); | |
alert(test.union(test3)); | |
alert(test.orderByDescending(function(t, t2) { return t - t2; })); | |
alert(test.contains(9)); | |
alert(test.distinct(function(t) { return t % 2; })); | |
alert(test2.groupBy(function(t) { return t.foo; })[1].values[1].bar); | |
END TESTS */ |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment