Returning a collection list filtered from an array

One thing I was trying to figure out lately is if it was possible to filter a collection from an array of id’s. Imagine you got a task model that lists another sub-task model. In your task model you got an array of sub-tasks, [1,4,7]. How would you go to retrieve those models?

The loop

The easiest way of doing this is by looping the array and saving the models one by one in a new collection.The code in your view would look like something like this:

var currentSubtask = new SubtaskCollection;
_.each(this.model.toJSON().subtasksArray, function(taskID){
	var mySubTask = allSubTasks.getOne(taskID)
	currentSubtask.add(mySubTask)
})

When we are about to show the sub-tasks for a master task, we loop our sub-tasks array and retrieve the sub-tasks one by one.

In our sub-tasks collection declaration, we would have this filter:

	getOne : function(SubTaskid){
		return this.filter(function(data) {
		  	return data.get("id") == SubTaskid;
		});
	},

Easy, we get one model each time. Obviously this technique is really not the most efficient. What we really want to achieve is not having to loop through our sub-tasks array on the view side, but directly pitch the array in the collection filter.

A better way

To do this we will have to change our filter, what we will do is check if each model through our collection exists in our sub-tasks array. If its not, its going to return -1 and in that case we are not going to keep it.

	getGuestById : function(subtasksArray){
		return this.select(function(model){
		    return (_.indexOf(subtasksArray, model.get("id")) > -1);
		  });
	}

This will return a list of models that you can add to a collection. We could also return a collection of those models directly wrapping everything with _()

	getGuestById : function(subtasksArray){
		return _(this.select(function(model){
		    return (_.indexOf(subtasksArray, model.get("id")) > -1);
		  }));
	}

That’s it

Here we go for filtering with arrays, in my next article I will use this technique to “bind” 2 models together and handle small relationships.

Cedric Dugas is an experienced front-end developer and founder of Position: Absolute, based in Montreal, Canada. When he is not doing CSS and jquery (does it ever happen?), he likes to read on web usability and play trumpet. Why don't you follow him on twitter.

2 Comments on "Returning a collection list filtered from an array"

  1. Ondra says:

    If I get it correctly, you have two collections, Tasks and Subtasks, that are tied together via Task atribbute subtasksArray. You could iterate over this array and use collection.get():

    var currentSubtask = new SubtaskCollection;
    _.each(this.model.toJSON().subtasksArray, function(taskID) {
    currentSubtask.add(allSubTasks.get(taskId));
    });

    Also consider having a subtask collection in your Task model…

  2. Johnny says:

    Great post.

    Just an FYI, _.select is now _.filter as of 1.2.1. It took a second for me to figure out why I was getting errors.

Got something to say? Go for it!