0

オブジェクトを含む多次元配列があり、特定のプロパティが含まれているオブジェクトを配列から削除したいと考えています。

コーヒースクリプト

for dataColumn in allDataColumns
    for brentSpiner, i in dataColumn
        console.log i, brentSpiner.refreshRate
        #dataColumn.remove i if brentSpiner.refreshRate is -1

console.log以下の行がコメントアウトされている場合、上記は期待どおりに機能します

for dataColumn in allDataColumns
    for brentSpiner, i in dataColumn
        console.log i, brentSpiner.refreshRate
        dataColumn.remove i if brentSpiner.refreshRate is -1

上記のエラーは次のようになりますbrentSpiner is undefined console.log(i, brentSpiner.refreshRate);

2行目の存在によって、上の行の変数が未定義になるのはどうしてでしょうか?

レンダリングされた JavaScript

失敗する

for (_i = 0, _len = allDataColumns.length; _i < _len; _i++) {
  dataColumn = allDataColumns[_i];
  for (i = _j = 0, _len1 = dataColumn.length; _j < _len1; i = ++_j) {
    brentSpiner = dataColumn[i];
    console.log(i, brentSpiner.refreshRate);
    if (brentSpiner.refreshRate === -1) {
      dataColumn.remove(i);
    }
  }
}

作品

for (_i = 0, _len = allDataColumns.length; _i < _len; _i++) {
  dataColumn = allDataColumns[_i];
  for (i = _j = 0, _len1 = dataColumn.length; _j < _len1; i = ++_j) {
    brentSpiner = dataColumn[i];
    console.log(i, brentSpiner.refreshRate);
  }
}

(補足: .remove は Resig を介して Array プロトタイプに追加されました)

アップデート

これは私の側の論理エラーでした。承認された回答を表示して、その理由を確認してください。ベローは私がやったことで、うまくいきました:

for dataColumn in allDataColumns
    i = 0
    len = dataColumn.length
    while i < len
        if dataColumn[i].refreshRate is -1
            dataColumn.remove i
            len--
        i++

レンダリング

for (_i = 0, _len = allDataColumns.length; _i < _len; _i++) {
  dataColumn = allDataColumns[_i];
  i = 0;
  len = dataColumn.length;
  while (i < len) {
    if (dataColumn[i].refreshRate === -1) {
      dataColumn.remove(i);
      len--;
    }
    i++;
  }
}
4

2 に答える 2

0

ループしているリストへの要素の追加/リストからの要素の削除は危険な操作であり、言語がこれを自動的に処理することは非常に困難です。このようなことをする必要がある場合は、ループを避け、for..inループに固執する必要がありwhileます。これが私がそのコードを書く方法です:

for dataColumn in allDataColumns
    i = 0
    while i < dataColumn.length
        brentSpiner = dataColumn[i]
        console.log i, brentSpiner.refreshRate
        if brentSpiner.refreshRate is -1
            dataColumn.remove i 
            i--
        i++

また、コードを段階的に変換して、どのようにしてそこに到達したかを確認します。

for dataColumn in allDataColumns
    for brentSpiner, i in dataColumn
        console.log i, brentSpiner.refreshRate
        dataColumn.remove i if brentSpiner.refreshRate is -1

まず、内側のループをwhileループにする必要があります。カウンター変数が長さよりも小さい限りループし、ループの最後でカウンターをインクリメントします。構文を保持するために、ループ内で最初に行うことは、ループ変数を設定することですbrentSpiner

for dataColumn in allDataColumns
    i = 0
    while i < dataColumn.length
        brentSpiner = dataColumn[i]
        console.log i, brentSpiner.refreshRate
        dataColumn.remove i if brentSpiner.refreshRate is -1
        i++

次の要素がスキップされるため、リストから要素を削除すると問題が発生します。例:リストは[1,2,3]i=0です。を削除することにした場合i、whileループの最後に、があり[2,3]ますi=1。次の項目はです3ので、スキップしまし2た。これを修正するために、現在のカウンターまたはその前にあるアイテムを削除するたびに、カウンターをデクリメントします。

for dataColumn in allDataColumns
    i = 0
    while i < dataColumn.length
        brentSpiner = dataColumn[i]
        console.log i, brentSpiner.refreshRate
        if brentSpiner.refreshRate is -1
            dataColumn.remove i 
            i--
        i++

要素も追加する場合は、非常に注意する必要があります。要素が挿入されている場所と、ループ内で処理する必要があるかどうかによっては、カウンターをインクリメントする必要がある場合があります。

于 2012-07-13T15:33:53.303 に答える
0

Coffeescript は のリストの長さを「凍結」してい_len1ます。エントリを削除すると、内側のループでリストの最後から実行されます。

私にはバグのように見えます。(配列の長さが変更される可能性があることをCoffeescriptに通知することになっている言語機能がない限り。)

于 2012-07-12T00:54:42.473 に答える