31

来自 Python,我喜欢 Coffeescript 从 Python 和 Perl 借用的许多特性(范围/切片、推导式、解构赋值)。Coffeescript 中是否有任何语法糖来模仿 Pythonenumeratezip( itertools.izip) 函数?

以下是我不太关心的模式:

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

# 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 ...
4

6 回答 6

29

forEach 有效地内置于:

a = ['a','b','c']
for el,i in a
    alert "Element #{el} is at index #{i}"
于 2011-04-11T04:08:58.347 回答
13

枚举:

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

zip/ zipWith(我从 Haskell 中学到了这些;我认为它们在 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

一些例子(经过测试):

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]

更新:重新实现 Haskell 风格,只是为了好玩。没有模式匹配就不那么酷了,但是哦..

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

哦,伙计,这很有趣。所以需要更多这样的问题:D

要点zipzipWith

于 2011-04-11T02:00:39.397 回答
8

对于压缩和其他此类实用功能,Underscore.js几乎是标准库——它恰好是由 CoffeeScript 背后的人 Jeremy Ashkenas 创建的。有了它,您可以将您的 zip 示例编写为

for elems in _.zip(arr1, arr2)
  x = elems[0]; y = elems[1]
  ...

或者更好

for [x, y] in _.zip(arr1, arr2)
  ...

使用模式匹配。但是请注意,它_.zip使用 和 的最大长度,arr1arr2不是最小值;因此,如果您不想处理undefined值,则应先截断较长的数组。

还有一个 Underscore 的 CoffeeScript 实现,Underscore.coffee,如果您想知道如何在 CoffeeScript 中实现特定循环,这是一个很好的地方。

于 2011-04-11T19:50:02.673 回答
5

CoffeeScript Cookbook列出了一个很好的 zip 函数实现:

# Usage: zip(arr1, arr2, arr3, ...)
zip = () ->
  lengthArray = (arr.length for arr in arguments)
  length = Math.min(lengthArray...)
  for i in [0...length]
    arr[i] for arr in arguments

zip([0, 1, 2, 3], [0, -1, -2, -3])
# => [[0, 0], [1, -1], [2, -2], [3, -3]]

http://coffeescriptcookbook.com/chapters/arrays/zip-function

于 2012-11-18T09:32:32.517 回答
2

不要忘记 CoffeeScript 只是 ECMAScript 的一种替代语法。至少对于您的第一个示例,有一个非常好的 ECMAscript 函数 ( Array.prototype.forEach),它已经完成了您想要的操作:

arr = ["a", "b", "c"]

arr.forEach (el, i) ->
  alert "Element #{el} is at index #{i}"

不幸的是,没有Array.prototype.zipor Array.prototype.zipWith。这似乎是一个很大的遗漏,特别是考虑到两者都有reducereduceRight,后者是许多其他语言所没有的。我的猜测是,这是一个简单的疏忽,我们将zip在该语言的某个未来版本中看到。

于 2011-04-11T01:40:01.863 回答
0

对于 zip,试试这个:

zip = (x...) ->
  (y[i] for y in x for i in [0...Math.min (y.length for y in x)...])

如果您喜欢一直拉到最后,请使用Math.max().

于 2016-03-24T18:42:42.160 回答