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);在萤火虫中

第二行的存在究竟如何导致上一行中的变量未定义?

渲染的 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

Coffeescript 将列表的长度“冻结”在_len1. 当您删除一个条目时,您将在内部循环中运行列表的末尾。

对我来说似乎是一个错误。(除非有一些语言特性你应该通知 Coffeescript 数组长度可能会改变。)

于 2012-07-12T00:54:42.473 回答
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 回答