开发者问题收集

使用 for 循环在 JavaScript 中删除数组中的子数组

2018-09-29
1228

如果子数组包含特定元素,我需要删除它。

function filteredArray(arr, elem) {
  let newArr = [];
  for (let i = 0; i < arr.length; i++){
    for (let j = 0; j < arr[i].length; j++) {
      if (arr[i][j] === elem) {
        arr.splice(i--, 1);
        newArr = [...arr]
      }
    }
  }
  return newArr;
}
console.log(filteredArray([[3, 2, 3], [1, 6, 3], [3, 13, 26], [19, 3, 9]], 19));

如果元素仅出现一次(例如 19),则上述代码运行正常。但如果我尝试第 3 项,则会得到: Uncaught TypeError:无法读取未定义的属性“length” 。有人可以解释一下这里发生了什么吗?

3个回答

使用 filter() includes() 已经足够简洁,您可能不需要单独的函数:

let array = [[3, 2, 3], [1, 6, 3], [3, 13, 26], [19, 3, 9]]
let filtered = array.filter(item => !item.includes(19));
console.log(filtered)
Mark
2018-09-29

问题是,一旦您从数组中 拼接 出一个项目,您的程序就会继续迭代已删除的内部数组的其余部分,就好像它仍然存在一样。在以 3 为目标的情况下,每个内部数组都将被删除,因为它们都包含 3 。在最后一次删除时,您会在内部数组的索引 1 处检测到 3 ,并 拼接 最后一个内部数组。在循环的下一次迭代中,程序在尝试索引空数组 [] 中的 [0][2] 时崩溃。

解决方案是添加一个 break 语句,如下所示;这将中止对已删除数组的进一步检查:

function filteredArray(arr, elem) {
  let newArr = [];
  
  for (let i = 0; i < arr.length; i++){
    for (let j = 0; j < arr[i].length; j++) {
      if (arr[i][j] === elem) {
        arr.splice(i--, 1);
        newArr = [...arr]
        break;
      }
    }
  }
  return newArr;
}
console.log(filteredArray([[3, 2, 3], [1, 6, 3], [3, 13, 26], [19, 3, 9]], 3));

话虽如此,您可以采取许多更简单的方法;例如,使用 array.filter() ,它根据其参数函数返回的真值选择元素:

const filteredArray = (a, target) => a.filter(e => !e.includes(target));

console.log(filteredArray([[3, 2, 3], [1, 6, 3], [3, 13, 26], [19, 3, 9]], 3));
console.log(filteredArray([[3, 2, 3], [1, 6, 3], [3, 13, 26], [19, 3, 9]], 19));
ggorlen
2018-09-29

尝试 Array.filter()

function filteredArray(arr, skip) {
  return arr.filter(function(sub) {
    return -1 === sub.indexOf(skip);
  });
}

var mixed = [[3, 2, 3], [1, 6, 2], [3, 13, 26], [19, 3, 9]];
console.log(filteredArray(mixed, 19));
console.log(filteredArray(mixed, 3));
2018-09-29