如何使用Linq从交错数组的多维数组中移除指定行?
问题描述
我有一个包含多维数组的交错数组,想要移除多维数组中的指定行,代码如下:
int[][,] arr = new int[4][,]; arr[0] = new int[,] { { 1, 2, 3 }, // <- 我想要移除这一行 { 4, 5, 6 }, { 5, 6, 7 }, { 8, 9, 10 } }; arr[1] = new int[,] { { 1, 2, 3, 4 }, { 5, 6, 7, 8 }, { 9, 10, 11, 12 }, { 13, 14, 15, 16 } }; arr[2] = new int[,] { { 1, 2, 3, 4, 5 }, { 5, 6, 7, 8, 9 }, { 10, 11, 12, 13, 14 }, { 15, 16, 17, 18, 19 } }; arr[3] = new int[,] { { 1, 2, 3, 4, 5, 6}, { 5, 6, 7, 8, 9, 10}, { 11, 12, 13, 14, 15, 16 }, { 17, 18, 19, 20, 21, 22 } }; int[,] removeArray = { { 1, 2, 3 } };
我尝试用Linq从arr[0]中移除{1,2,3},代码如下:
arr = arr .Where((val, i) => i != 0) .ToArray();
但这段代码会删除整个arr[0],请问如何用Linq实现仅移除指定的{1,2,3}行?
解决方案
要实现仅移除arr[0]中的指定行,需要先将二维数组arr[0]转换为可枚举的行集合,筛选掉目标行后再转换回二维数组,最后替换原交错数组中的arr[0]。
1. 实现数组行内容比较方法
直接比较二维数组的引用无法判断内容是否一致,需要自定义方法对比两个一维数组(二维数组的行)的内容:
private static bool ArraysEqual(int[] a, int[] b) { if (a.Length != b.Length) return false; for (int i = 0; i < a.Length; i++) { if (a[i] != b[i]) return false; } return true; }
2. 处理目标二维数组arr[0]
使用Linq将arr[0]的每一行提取为一维数组,筛选掉与removeArray第一行内容匹配的行,再将筛选后的行转换回二维数组:
// 把removeArray的目标行转成一维数组 int[] targetRow = Enumerable.Range(0, removeArray.GetLength(1)) .Select(col => removeArray[0, col]) .ToArray(); // 处理arr[0]:提取行、筛选目标行、转回二维数组 arr[0] = arr[0] .Cast<int>() .Chunk(arr[0].GetLength(1)) // 将一维序列按每行列数分块,得到每行的一维数组 .Where(row => !ArraysEqual(row, targetRow)) .SelectMany(row => row) // 将筛选后的行合并为一维序列 .ToArray() .To2DArray(arr[0].GetLength(1)); // 自定义方法转二维数组
3. 实现一维数组转二维数组的扩展方法
补充一个将一维数组转换为指定列数的二维数组的方法:
private static int[,] To2DArray(this int[] source, int columns) { int rows = source.Length / columns; int[,] result = new int[rows, columns]; for (int i = 0; i < rows; i++) { for (int j = 0; j < columns; j++) { result[i, j] = source[i * columns + j]; } } return result; }
完整示例代码
using System; using System.Linq; class Program { static void Main() { int[][,] arr = new int[4][,]; arr[0] = new int[,] { { 1, 2, 3 }, { 4, 5, 6 }, { 5, 6, 7 }, { 8, 9, 10 } }; arr[1] = new int[,] { { 1, 2, 3, 4 }, { 5, 6, 7, 8 }, { 9, 10, 11, 12 }, { 13, 14, 15, 16 } }; arr[2] = new int[,] { { 1, 2, 3, 4, 5 }, { 5, 6, 7, 8, 9 }, { 10, 11, 12, 13, 14 }, { 15, 16, 17, 18, 19 } }; arr[3] = new int[,] { { 1, 2, 3, 4, 5, 6}, { 5, 6, 7, 8, 9, 10}, { 11, 12, 13, 14, 15, 16 }, { 17, 18, 19, 20, 21, 22 } }; int[,] removeArray = { { 1, 2, 3 } }; // 处理arr[0]移除指定行 int[] targetRow = Enumerable.Range(0, removeArray.GetLength(1)) .Select(col => removeArray[0, col]) .ToArray(); arr[0] = arr[0] .Cast<int>() .Chunk(arr[0].GetLength(1)) .Where(row => !ArraysEqual(row, targetRow)) .SelectMany(row => row) .ToArray() .To2DArray(arr[0].GetLength(1)); // 验证结果:输出arr[0]的所有元素 for (int i = 0; i < arr[0].GetLength(0); i++) { for (int j = 0; j < arr[0].GetLength(1); j++) { Console.Write(arr[0,i,j] + " "); } Console.WriteLine(); } } private static bool ArraysEqual(int[] a, int[] b) { if (a.Length != b.Length) return false; for (int i = 0; i < a.Length; i++) { if (a[i] != b[i]) return false; } return true; } private static int[,] To2DArray(this int[] source, int columns) { int rows = source.Length / columns; int[,] result = new int[rows, columns]; for (int i = 0; i < rows; i++) { for (int j = 0; j < columns; j++) { result[i, j] = source[i * columns + j]; } } return result; } }
关键说明
Cast<int>():将二维数组转换为一维的IEnumerable<int>,方便后续分块处理。Chunk():.NET 6及以上版本可用,将一维序列按每行的列数分割,得到每行的一维数组。ArraysEqual:自定义方法判断两行内容是否完全一致,确保精准筛选目标行。To2DArray:扩展方法将筛选后的一维序列重新转换为二维数组,替换原arr[0]。
内容的提问来源于stack exchange,提问作者Valkyrie
相关产品推荐
相关产品推荐

