Skip to content

Commit

Permalink
Implemented groupBy as discussed in issue caolan#214, along with docu…
Browse files Browse the repository at this point in the history
…mentation and tests
  • Loading branch information
brianmaissy committed Feb 6, 2013
1 parent b62eff0 commit 61080ee
Show file tree
Hide file tree
Showing 3 changed files with 90 additions and 0 deletions.
33 changes: 33 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,7 @@ So far its been tested in IE6, IE7, IE8, FF3.6 and Chrome 5. Usage:
* [reduce](#reduce)
* [detect](#detect)
* [sortBy](#sortBy)
* [groupBy](#groupBy)
* [some](#some)
* [every](#every)
* [concat](#concat)
Expand Down Expand Up @@ -446,6 +447,38 @@ async.sortBy(['file1','file2','file3'], function(file, callback){

---------------------------------------

<a name="groupBy" />
### groupBy(arr, iterator, callback)

Groups a list by the results of running each value through an async iterator.

__Arguments__

* arr - An array to iterate over.
* iterator(item, callback) - A function to apply to each item in the array.
The iterator is passed a callback which must be called once it has completed
with an error (which can be null) and a value to use as the group criteria.
* callback(err, results) - A callback which is called after all the iterator
functions have finished, or an error has occurred. Results is an object whose
keys are the unique values given by the iterator and whose corresponding
values are arrays containing the elements of the original list which the
iterator mapped to that value, in no particular order.

__Example__

```js
async.groupBy(['file1','file2','file3'], function(file, callback){
fs.stat(file, function(err, stats){
callback(err, stats.uid);
});
}, function(err, results){
// results is now an object mapping user ids to an array of the names of
// files that user owns, e.g. {1000: ['file2'], 1001: ['file1', 'file3']}
});
```

---------------------------------------

<a name="some" />
### some(arr, iterator, callback)

Expand Down
31 changes: 31 additions & 0 deletions lib/async.js
Original file line number Diff line number Diff line change
Expand Up @@ -385,6 +385,37 @@
});
};

async.groupBy = function (arr, iterator, callback) {
async.map(arr, function (x, callback) {
iterator(x, function (err, criteria) {
if (err) {
callback(err);
}
else {
callback(null, {value: x, criteria: criteria});
}
});
}, function (err, results) {
if (err) {
return callback(err);
}
else {
var groupedResults = {};
for (var i = 0; i < results.length; i++) {
var criteria = results[i].criteria;
var value = results[i].value
if (typeof groupedResults[criteria] !== 'undefined') {
groupedResults[criteria].push(value);
}
else {
groupedResults[criteria] = [value];
}
}
callback(null, groupedResults);
}
});
};

async.auto = function (tasks, callback) {
callback = callback || function () {};
var keys = _keys(tasks);
Expand Down
26 changes: 26 additions & 0 deletions test/test-async.js
Original file line number Diff line number Diff line change
Expand Up @@ -1148,6 +1148,32 @@ exports['sortBy'] = function(test){
});
};

exports['groupBy'] = function(test){
var alice = {name: 'Alice', age: 20};
var bob = {name: 'Bob', age: 21};
var carol = {name: 'Carol', age: 20};
var dave = {name: 'Dave', age: 22};
var eve = {name: 'Eve', age: 21};
var people = [alice, bob, carol, dave, eve];
function getAge(person, callback){
callback(null, person.age);
}
function peopleSort(firstPerson, secondPerson){
if(firstPerson.name < secondPerson.name) return -1;
else if(firstPerson.name > secondPerson.name) return 1;
else return 0;
}
function samePeople(firstArray, secondArray){
test.same(firstArray.sort(peopleSort), secondArray.sort(peopleSort));
}
async.groupBy(people, getAge, function(err, result){
samePeople(result[20], [alice, carol]);
samePeople(result[21], [bob, eve]);
samePeople(result[22], [dave]);
test.done();
});
};

exports['apply'] = function(test){
test.expect(6);
var fn = function(){
Expand Down

0 comments on commit 61080ee

Please sign in to comment.