This question already has answers here:
Why does changing an Array in JavaScript affect copies of the array?
                                
                                    (11个答案)
                                
                        
                                4个月前关闭。
            
                    
我的练习是创建一个带有两个参数的函数:一个多维数组和一个值。我必须返回一个新数组,其中删除了所有包含该值的子数组。我的想法是使用嵌套for循环在每个子数组中搜索值。如果找到匹配项,则删除子数组并结束内部循环。但是代码运行不正常,调试时发现以下问题:



//Assingment is from FreeCodeCamp
function filteredArray(arr, elem) {
  let newArr = [];
  //my solution start here
  newArr = arr;
  for (let i = 0; i < arr.length; i++) {
    for (let j = 0; j < arr[i].length; j++) {
      //debugging
      console.log( "i", i);
      console.log( 'j', j);
      console.log(arr);
      console.log(arr[i]);
      console.log(arr[i][j]);
      //end debugging
      if (arr[i][j] == elem) {
        newArr.shift();   //remove the sub-array
       j = arr[i].length; //end the inner loop
      }
      console.log('newArr',newArr);
    }
  }
  //my solution end here
  return newArr;
}

// change code here to test different cases:
console.log(filteredArray([[3, 2, 3], [1, 6, 3], [3, 13, 26], [19, 3, 9]], 3));





结果是:

"i" 0
"j" 0
[[3,2,3],[1,6,3],[3,13,26],[19,3,9]]
[3,2,3]
3
"newArr" [[1,6,3],[3,13,26],[19,3,9]]
"i" 1
"j" 0
[[1,6,3],[3,13,26],[19,3,9]]
[3,13,26]
3
"newArr" [[3,13,26],[19,3,9]]
[[3,13,26],[19,3,9]]


该代码在第一个i = 0循环中运行良好。但是在下一个循环中,i = 1,参数数组被更改。我以为它是函数的输入数组,但是结果是,即使我没有对该数组进行任何更改,第一个子数组也被删除了。有人可以帮我解释一下吗?

最佳答案

通过说newArr = arr;,您将保持对原始数组的相同引用,因此对一个数组的任何更改都会影响另一个数组。复制数组有多种方法,一种是使用spreed运算符([...arr])进行浅表复制,这对于您的特定示例很好。另一件事是shift()方法将始终返回或从数组中删除第一个元素。您可以使用array splice()方法对数组执行基于索引的操作,例如添加,删除或替换元素。



function filteredArray([...arr], elem) {
  for (let i = 0; i < arr.length; i++) {
    for (let j = 0; j < arr[i].length; j++) {
      if (arr[i][j] == elem) {
        arr[i].splice(j, 1);
      }
    }
  }
  return arr;
}

console.log(filteredArray([[3, 2, 3], [1, 6, 3], [3, 13, 26], [19, 3, 9]], 3));





您还可以使用内置的map()filter()方法来缩短步骤:



filteredArray = (arr, elem) => arr.map( a => a.filter(value => value != elem));

console.log(filteredArray([[3, 2, 3], [1, 6, 3], [3, 13, 26], [19, 3, 9]], 3));





编辑:

上面的答案假设您只想删除该元素。如果您要删除包含该元素的子数组:



function filteredArray([...arr], elem) {
  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);
        i--;
        break;
      }
    }
  }
  return arr;
}

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], [13, 26], [19, 3, 9]], 3));





或简而言之:



filteredArray = (arr, elem) => arr.filter( a => !a.includes(elem));

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], [13, 26], [19, 3, 9]], 3));

08-18 17:04
查看更多