C#数组调整大小异常 如何正确删除数组0值保留非0元素
问题分析
你的代码存在3处核心错误,直接导致运行结果不符合预期:
- 数组初始化的遍历逻辑完全错误:
foreach (int i in arr)遍历int数组时,循环变量i取到的是数组内存储的元素值,不是位置索引。你刚创建的int数组所有元素默认值都是0,所以这段循环从头到尾都在反复修改arr[0]的值,剩下29个数组位置从来没被赋过随机值,一直是默认0,你写的zeroCounter统计结果从根上就是错的。 - 结果输出的遍历逻辑也错了:和上面的问题一样,过滤后的数组用foreach遍历的时候,循环变量就是你要输出的非0数字本身,你写
arr[i]相当于拿数字当数组索引去取值,轻则取到错误的数,重则直接触发索引越界异常。 - 存在冗余的错误操作:
arr.Where(i => i != 0).ToArray()执行完成后,返回的新数组本来就只包含所有非0元素,长度自动匹配非0元素的总数量,后面调用Array.Resize完全是画蛇添足,再加上你之前zeroCounter的计数本身不准,这步Resize反而可能把已经过滤好的有效元素截掉。
修正后代码
int SIZE = 30; var rand = new Random(); int[] arr = new int[SIZE]; // 数组赋值用for循环走索引,避免foreach拿不到索引的问题 for (int idx = 0; idx < arr.Length; idx++) { arr[idx] = rand.Next(0, 11); Console.Write(arr[idx] + " "); } Console.WriteLine(); // 直接用LINQ过滤0值生成新数组,不需要额外计数、不需要Resize arr = arr.Where(num => num != 0).ToArray(); // 遍历输出直接取循环变量即可,不要把元素当索引用 foreach (int num in arr) { Console.Write(num + " "); }
可选的无LINQ实现
如果你不想用LINQ的Where方法,也可以手动实现过滤逻辑,本质逻辑一致:
int SIZE = 30; var rand = new Random(); int[] arr = new int[SIZE]; for (int idx = 0; idx < arr.Length; idx++) { arr[idx] = rand.Next(0, 11); Console.Write(arr[idx] + " "); } Console.WriteLine(); // 先统计非0元素个数 int nonZeroCount = 0; foreach (int num in arr) { if (num != 0) nonZeroCount++; } // 创建对应长度的新数组,拷贝非0元素 int[] result = new int[nonZeroCount]; int resultIdx = 0; foreach (int num in arr) { if (num != 0) { result[resultIdx] = num; resultIdx++; } } // 输出结果 foreach (int num in result) { Console.Write(num + " "); }
内容的提问来源于stack exchange,提问作者Gleb Shapovalov
相关产品推荐
相关产品推荐

