2

I am quite new to coffeescript and I am wondering if any more experienced users could point suggest a refactoring for the following code:

splitCollection: =>
  maxLength = Math.ceil(@collection.length / 3)

  sets = Math.ceil(@collection.length / maxLength)
  start = 0    

  for x in [1..sets]   
    if x != sets
      @render new BusinessUnits(@collection.models.slice(start, (maxLength + start)))
    else
      @render new BusinessUnits(@collection.models.slice(start, (@collection.length)))
    start+= maxLength

There does not appear to be a while loop in coffeescript which seems to suggest a better mechanism.

Any suggestions appreciated.

3 Answers 3

5

Looks like you are using Backbone.js, which includes Underscore.js, which has the groupBy function.

You could create a "bucketNumber" function:

bucketNumber = (value, index) ->
    Math.floor( index / @collection.length * 3 )

Then group your collection:

sets = @collection.groupBy bucketNumber

Now, assuming ten items, sets should look something like this:

{0: [{}, {}, {}], 1: [{}, {}, {}], 2: [{}, {}, {}, {}]}

From here, it becomes rather straight-forward

for bucketNumber, bucket of sets
    @render new BusinessUnits( bucket )

Here is a jsFiddle showing it in action

Sign up to request clarification or add additional context in comments.

1 Comment

That is a nice answer and what I will probably use but I am trying to understand coffeescript better.
1

You don't need to keep track of your position twice, x is enough:

splitCollection: =>
    setSize = Math.ceil @collection.length / 3
    sets = Math.ceil @collection.length / maxLength

    for x in [1..sets]
        @render new BusinessUnits @collection.models[x * setSize...(x+1) * setSize]

Note that there is nothing wrong with passing slice an end greater than the array length.

Comments

0

If I understand your code, you want to split an array in 3 parts (the last one can have less items). In this case write the reusable abstraction for the task. Using underscore:

splitCollection: =>
  group_size = Math.ceil(@collection.size() / 3)
  _.each _(@collection.models).inGroupsOf(group_size), (group) ->
    @render(new BusinessUnits(group))

_.inGroupsOf can be written:

_.mixin({
  inGroupsOf: function(array, n) {
    var output = [];
    for(var index=0; index < array.length; index += n) {
      output.push(array.slice(index, index+n));
    }
    return output;
  }
});

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.