Alex Rivera | Logout

enumerate and zip within Coffeescript?

Asked 2011-04-11T01:10:55.590
31

Coming from Python, I like many of the features that Coffeescript borrows from Python and Perl (ranges/slices, comprehensions, destructuring assignments). Is there any syntactic sugar in Coffeescript to mimic Python's enumerate or zip (itertools.izip) functions?

Here are the patterns that I don't care much for:

# an enumerate call would be helpful here
i = 0
for x in arr
  ... use x and i ...
  i++

and

# a zip would be useful here
n = Math.min(arr1.length,arr2.length)
for i in 0...n
  x = arr1[i]; y = arr2[i]
  ... use x and y ...
Edit
Report

1 Answer

13

Enumerate:

arr.forEach (x, i) ->
    ... use x and i ...

zip / zipWith (I learned these from Haskell; I assume they mean the same thing in Python?):

zip = (arr1, arr2) ->
  basic_zip = (el1, el2) -> [el1, el2]
  zipWith basic_zip, arr1, arr2

zipWith = (func, arr1, arr2) ->
  min = Math.min arr1.length, arr2.length
  ret = []

  for i in [0...min]
    ret.push func(arr1[i], arr2[i])

  ret

Some examples (tested):

zip([1, 2, 3], [4, 5, 6])          # => [[1, 4], [2, 5], [3, 6]]

add = (el1, el2) -> el1 + el2
zipWith(add, [1, 2, 3], [4, 5, 6]) # => [5, 7, 9]

Update: Reimplemented Haskell-style, just for fun. Not as cool without the pattern matching, but oh well..

zipWith = (func, arr1, arr2) ->
  return [] if arr1.length is 0 or arr2.length is 0

  el1 = arr1.shift()
  el2 = arr2.shift()

  ret_arr = zipWith func, arr1, arr2
  ret_arr.unshift func(el1, el2)

  ret_arr

Oh, man, this was fun. SO needs more questions like this :D

Gist for zip and zipWith

answered 2011-04-11T02:00:39.397

Your Answer