JavaScript没有像预期的那样迭代

时间:2018-12-07 19:59:27

标签: javascript

谁能告诉我为什么我的JS不遍历循环并删除数组中非“ 10”的项?

据我了解,它应该检查数组中的每个项目并删除非10的项目,然后返回其余的“ 10”项目。

我当前的输出是:[ <1 empty item>, 10, 50, 10 ]

我看到了一些答案,它们创建了一个单独的数组并将10的项目压入其中,然后返回该数组,但是为什么我的代码不起作用?

function getElementsThatEqual10AtProperty(obj, key) {
  if (obj.key.length === 0) {
    return [];
  } else if (!obj.hasOwnProperty(key)) {
    return [];
  } else {
    for (var i = 0; i < obj.key.length; i++) {
      if (obj[key][i] !== 10) {
        delete obj[key][i];
      }
      return obj.key;
    }
  }
}

var obj = {
  key: [1000, 10, 50, 10]
};
var output = getElementsThatEqual10AtProperty(obj, 'key');
console.log(output);

6 个答案:

答案 0 :(得分:1)

您的代码有什么问题

主要问题是您正在循环内执行return,这意味着该函数在您的第一次迭代中碰到该行时将完全退出。

第二个问题更多是一个建议,但我不建议使用delete。删除对象属性后, delete不会更新数组的length或索引

var array = [1, 2, 3, 4];
delete array[0];
console.log(array.length);

假设,您可以将.filter(n=>n)链接到它,一切都会好起来,但它仍然是多余的一组不必要的迭代。


解决方法

从数组中过滤项目的最简单方法是使用以下名称的方法:Array.filter()

您更新后的功能可能看起来像这样。

function getElementsThatEqual10AtProperty(obj, key) {
  if (Array.isArray(obj[key])                //Is it an array?
    return obj[key].filter(n => n === 10);   //Filter it for 10s
  else
    return [];
}

var obj = {
  key: [1000, 10, 50, 10]
};

var output = getElementsThatEqual10AtProperty(obj, 'key');
console.log(output);

或者,如果您希望简洁:

const get10s = (obj, key) => Array.isArray(obj[key]) ? obj[key].filter(n => n === 10) : [];
var obj = { key: [1000, 10, 50, 10] };
console.log( get10s(obj, 'key') );

答案 1 :(得分:1)

为什么您的代码无法正常工作

  • 您的return语句位于for循环内,因此一旦您的if条件失败,它将立即返回控制。
  • 您正在使用delete,它将删除该元素,但其他元素的索引仍与以前相同。这样您会得到类似[undefined,10,undefined,10]的信息。

这是您的代码的工作模式。

function getElementsThatEqual10AtProperty(obj, key) {
  if (obj.key.length === 0) {
    return [];
  } else if (!obj.hasOwnProperty(key)) {
    return [];
  } else {
    let temp = []
    for (var i = 0; i < obj.key.length; i++) {
      if (obj[key][i] == 10) {
        temp.push(obj[key][i])
      }
    }
    return temp;
  }
}

var obj = {
  key: [1000, 10, 50, 10]
};
var output = getElementsThatEqual10AtProperty(obj, 'key');
console.log(output);

但是我建议您使用它,因为它既干净又简单

function getElementsThatEqual10(array) {
  return array.filter(element => element === 10);
}

var obj = {
  key: [1000, 10, 50, 10]
};
var output = getElementsThatEqual10(obj.key);
console.log(output);

答案 2 :(得分:1)

替代

如果您愿意使用其他方法,则可以尝试使用filter来解析所要获取的值:

const getElementsThatEqual10AtProperty = (obj, key) => obj[key].filter(v => v === 10)

var obj = {
  key: [1000, 10, 50, 10]
};
var output = getElementsThatEqual10AtProperty(obj, 'key');

console.log(output);


您的代码

鉴于您当前的方法,存在三个问题:

  1. 由于要传递 key 作为参数,因此您应该在obj.key的地方使用obj[key]
  2. 在阵列上操作时,
  3. delete obj[key][i]不会表现出预期的效果。正如@TinyGiant所提到的,“它不会对索引重新排序以删除结果的空槽。”
  4. return obj.key应该为return obj[key],并且应该将其移到循环外,因为它在第一次迭代结束时就退出了循环

如果要保留此方法,我建议使用obj[key].splice(i,1)而不是delete,这会改变数组。但是,由于要对活动数组进行突变,由于元素已移动,因此还必须修改i。见下文:

function getElementsThatEqual10AtProperty(obj, key) {
  if (obj[key].length === 0) {
    return [];
  } else if (!obj.hasOwnProperty(key)) {
    return [];
  } else {
    for (var i = 0; i < obj.key.length; i++) {
      if (obj[key][i] !== 10)
        obj[key].splice(i--,1)                    // remove value then alter i
    }
    return obj[key]                               // moved outside of the loop
  }
}

var obj = {
  key: [1000, 10, 50, 10]
};
var output = getElementsThatEqual10AtProperty(obj, 'key');
console.log(output);

答案 3 :(得分:0)

这是一种奇怪的方法设计。它使变异并返回结果?通常,最好选择其中一个(请参见CQS)。

此外,您的原始方法过度耦合到对象结构。最好使它仅在数组上运行,而不留任何对象键。

请考虑以下内容:

function getElementsThatEqual10(array) {
  return array.filter(n => n == 10);
}

var obj = {
  key: [1000, 10, 50, 10]
};
var output = getElementsThatEqual10(obj.key);
console.log(output);

答案 4 :(得分:-1)

早期返回返回仅完成删除第一个元素后退出循环(由于对象不相关,此处简化为简单数组):

let objKey = [1000, 10, 50, 10];

for (var i = 0; i < objKey.length; i++) {
  if (objKey[i] !== 10) {
    // Here it deletes 1000, the first element
    delete objKey[i];
  }
  // then it returns [undefined, 10, 50, 10]
  return objKey;
}

您可以将return语句从循环中移到getElementsThatEqual10AtProperty函数结束之前。

其他人已经提出了更优雅的方法。

答案 5 :(得分:-2)

您可以这样写以删除正确的项目,因为您正在for循环中返回,因此仅删除了第一项。

您可以使用splice方法而不是delete,因为delete仅删除引用,而不删除数组的位置。

function getElementsThatEqual10AtProperty(obj, key) {
  if (obj[key].length === 0) {
    return [];
  } else if (!obj.hasOwnProperty(key)) {
    return [];
  } else {
    for (var i = 0; i < obj[key].length; i++) {
      if (obj[key][i] !== 10) {
        obj[key].splice(i, 1);
        i--;
      }
    }
    return obj[key];
  }
}

var obj = {
  key: [1000, 10, 50, 10]
};
var output = getElementsThatEqual10AtProperty(obj, 'key');
console.log(output);