在 Coffeescript 中枚举和压缩?

发布于 2024-10-31 12:00:36 字数 489 浏览 0 评论 0原文

来自 Python,我喜欢 Coffeescript 从 Python 和 Perl 借用的许多功能(范围/切片、推导式、解构赋值)。 Coffeescript 中是否有任何语法糖可以模仿 Python 的 enumeratezip (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 ...

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

眼眸 2024-11-07 12:00:36

forEach 有效地内置于:

a = ['a','b','c']
for el,i in a
    alert "Element #{el} is at index #{i}"

forEach is effectively built in:

a = ['a','b','c']
for el,i in a
    alert "Element #{el} is at index #{i}"
何处潇湘 2024-11-07 12:00:36

枚举:

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

Gist for zipzipWith

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

泪意 2024-11-07 12:00:36

对于压缩和其他此类实用函数,Underscore.js 几乎是标准库 - 而且它恰好是由 Jeremy 创建的Ashkenas,CoffeeScript 背后的人。有了它,您可以

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

编写您的 zip 示例,或者更好

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

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

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

For zipping and other such utility functions, Underscore.js is pretty much the standard library—and it happens to have been created by Jeremy Ashkenas, the man behind CoffeeScript. With it, you could write your zip example as

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

or better yet

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

using pattern-matching. Note, however, that _.zip uses the max length of arr1 and arr2, not the min; so if you don't want to handle undefined values, you should truncate the longer array first.

There's also a CoffeeScript implementation of Underscore, Underscore.coffee, which is a great place to look if you're wondering how to implement a particular loop in CoffeeScript.

终难遇 2024-11-07 12:00:36

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

The CoffeeScript Cookbook lists a nice implementation of a zip function:

# 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

千柳 2024-11-07 12:00:36

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

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

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

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

Don't forget that CoffeeScript is just an alternate syntax for ECMAScript. At least for your first example, there is a perfectly good ECMAscript function (Array.prototype.forEach), which already does what you want:

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

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

Unfortunately, there is no Array.prototype.zip or Array.prototype.zipWith. That seems to be a pretty big omission, especially considering that there is both reduce and reduceRight, the latter of which many other languages don't have. My guess is that it is a simple oversight, and we are going to see zip in some future version of the language.

会发光的星星闪亮亮i 2024-11-07 12:00:36

对于 zip,请尝试以下方法:

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

如果您希望一直压缩到最后,请使用 Math.max()。

For zip, try this one:

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

If you prefer to zip all the way to the end, use Math.max().

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文