31

Python 出身なので、Coffeescript が Python と Perl から借用した多くの機能 (範囲/スライス、内包表記、構造化代入) が気に入っています。enumeratePython のor zip( itertools.izip) 関数を模倣するために、Coffeescript にシンタックス シュガーはありますか?

私があまり気にしないパターンは次のとおりです。

# 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

ああ、これは楽しかった。SOには、このような質問がもっと必要です:D

zipとの要旨zipWith

于 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使用することに注意してください。したがって、値を処理したくない場合は、最初に長い配列を切り捨てる必要があります。arr1arr2undefined

Underscore の CoffeeScript 実装である Underscore.coffee もあります。これは、CoffeeScript で特定のループを実装する方法を知りたい場合に参照するのに最適な場所です。

于 2011-04-11T19:50:02.673 に答える
5

The 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.zipまたははありませんArray.prototype.zipWithreduce特にとがありreduceRight、後者は他の多くの言語にはないことを考えると、これはかなり大きな省略のようです。私の推測では、これは単純な見落としであり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 に答える