Ruby Enumerable’s each_cons

nn

Ruby’s Enumerable module has a useful method called each_cons. It’s useful when you need to perform an operation over N consecutive items. Here’s an example:

nn

a = [1,2,3,4,5,6]na.each_cons(3) { |l| puts l.inspect }nn# outputn[1, 2, 3]n[2, 3, 4]n[3, 4, 5]n[4, 5, 6]nn

nn

It’s like a moving window, N items wide, that returns each consecutive N items. I don’t use it very often but occasionally it comes in very handy.

nn

eachCons in Coffeeillegalscript

nn

I needed to do something similar in a web application recently. I was hoping Underscore.js would have an easy way to do it but it doesn’t have one built in. You can build a function in Javaillegalscript to do it without too much effort. Here it is written in Coffeeillegalscript

nn

# Calls function fn with consSize items from array a.neachCons = (a, consSize, fn) ->n  for i in [0..(a.length-consSize)]n    fn(a[i..i+consSize-1])nn# Sample usagena = [1,2,3,4,5,6]nprinter = (s) -> console.log(s)neachCons(a, 3, printer)nn

nn

Try this in jsfiddle

nn

Underscore.js with eachCons mixin

nn

That works but if you’re using underscore.js throughout your app then you’ll have two different styles of iteration functions. You can extend Underscore.js using the mixin function. The following coffeeillegalscript shows how to extend Underscore.js to support eachCons.

nn

# Define a function that takes:n# obj - an object to iterate overn# consSize - the number of consecutive items to get n# iterator - a function we'll with each subset of itemsn# context - becomes 'this' when in the iterator functionnconser = (obj, consSize, iterator, context) ->n  for i in [0..obj.length-consSize]n    stop = i + consSizen    stop = obj.length if stop > obj.lengthn    slice = obj[i...stop]n    iterator.call(context, slice, i, obj)nn_.mixin({"eachCons": conser})nn

nn

Then we can call the eachCons underscore function like this

nn

a = [1,2,3,4,5,6]n_.eachCons(a, 3, (l) -> console.log(l) )nn

nn

Try this in jsfiddle

n