我有一个包含对象的多维数组,如果它们包含特定属性,我希望从数组中删除它们。
的CoffeeScript
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);
在firebug中
第二行的存在如何导致上一行中的变量变得不确定?
RENDERED 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++;
}
}
答案 0 :(得分:0)
Coffeescript正在“冻结”_len1
中列表的长度。删除条目时,您将在内循环中运行列表的末尾。
对我来说看起来像个错误。 (除非有一些语言功能,你应该通知Coffeescript数组长度可能会改变。)
答案 1 :(得分: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++
如果我们还要添加元素,我们必须非常小心。我们可能必须递增计数器,具体取决于元素的插入位置以及是否应在循环中处理。