C# 在列表中查找第一个元素与匹配条件的元素相同的所有数组
这是一个很难回答的问题 在C#中,我有一组C# 在列表中查找第一个元素与匹配条件的元素相同的所有数组,c#,arrays,list,multidimensional-array,C#,Arrays,List,Multidimensional Array,这是一个很难回答的问题 在C#中,我有一组int[,]数组存储在列表路径中,每个数组保存一组Coordenate以形成路径。 一个例子是{0,0},{0,1},{1,1},{2,1} 现在,我想在路径中保留所有第一个索引与所有匹配条件的路径的第一个索引之一相同的路径 为了更好地说明我的意思,假设我得到了所有奇数长度的路径: paths.Where(x => x.GetLength(0) % 2 == 1).ToList(); 假设它返回一个列表,其中包含一些数组,例如,其第一个坐标为{0
int[,]
数组存储在列表路径中,每个数组保存一组Coordenate以形成路径。
一个例子是{0,0},{0,1},{1,1},{2,1}
现在,我想在路径中保留所有第一个索引与所有匹配条件的路径的第一个索引之一相同的路径
为了更好地说明我的意思,假设我得到了所有奇数长度的路径:
paths.Where(x => x.GetLength(0) % 2 == 1).ToList();
假设它返回一个列表,其中包含一些数组,例如,其第一个坐标为{0,0}或{0,1}。我希望路径成为路径。其中(x=>x
的第一个坐标是{0,0}或{0,1})
。我怎样才能做到这一点
希望我的意思是可以理解的。像这样:
var filteredPaths = paths.Where(x => x[0, 0] == 0 && x[0, 1] == 0 || x[0, 0] == 0 && x[0, 1] == 1);
或者,如果您希望继续使用相同的集合类型:
List<int[,]> filteredPaths = paths.Where(x => x[0, 0] == 0 && x[1, 0] == 0 || x[0, 0] == 0 && x[1, 0] == 1).ToList();
List filteredPaths=路径。其中(x=>x[0,0]==0&&x[1,0]==0 | | x[0,0]==0&&x[1,0]==1)。ToList();
假设下面的列表表示多维元素,那么这里有一个例子:
List<short[,]> paths = new List<short[,]>
{
new short[3, 2] { { 0, 0 }, { 4, 5 }, { 6, 7 } },
new short[3, 2] { { 0, 1 }, { 8, 9 }, { 10, 11 } },
new short[3, 2] { { 1, 1 }, { 1, 3 } ,{ 6, 1 } },
new short[3, 2] { { 2, 1 }, { 3, 5 }, { 7, 7 } }
};
定义一个扩展方法,使我们能够将多维数组截断为仅用于过滤的第一个坐标
static class Helper
{
public static IEnumerable<short> SliceRow(this short[,] array, short row)
{
for (var i = array.GetLowerBound(1); i <= array.GetUpperBound(1); i++)
{
yield return array[row, i];
}
}
}
如果您打算使用当前的数据结构,那么您可以做到这一点,但是语法不会很好。这基本上就像A.Milto在他的回答中所建议的,只是需要进行边界检查,以避免在路径为空的情况下抛出异常。因此,如果您这样定义路径:
var arrayPaths = new List<int[,]>();
arrayPaths.Add(new[,] { { 0, 0 }, { 0, 1 }, { 1, 1 }, { 2, 1 } }); // Include: starts with (0, 0)
arrayPaths.Add(new[,] { { 0, 1 }, { 0, 1 }, { 1, 1 }, { 2, 1 } }); // Include: starts with (0, 1)
arrayPaths.Add(new[,] { { 1, 0 }, { 0, 1 }, { 1, 1 }, { 2, 1 } }); // Exclude: starts with (1, 0)
arrayPaths.Add(new int[0,0]); // Exclude: has no data
Neville Nazerane在他的评论中提出了一个很好的建议:使用一个数据结构而不是整数数组来表示一个点应该会产生更容易理解的代码。例如,假设您这样定义一个坐标:
public struct Coordinate
{
public Coordinate(int x, int y)
{
X = x;
Y = y;
}
public int X { get; }
public int Y { get; }
public bool Equals(int x, int y) =>
X == x && Y == y;
}
然后您可以定义上面给出的路径集,如下所示:
var objectPaths = new List<List<Coordinate>>();
objectPaths.Add(new List<Coordinate> { new Coordinate(0, 0), new Coordinate(0, 1), new Coordinate(1, 1), new Coordinate(2, 1) });
objectPaths.Add(new List<Coordinate> { new Coordinate(0, 1), new Coordinate(0, 1), new Coordinate(1, 1), new Coordinate(2, 1) });
objectPaths.Add(new List<Coordinate> { new Coordinate(1, 0), new Coordinate(0, 1), new Coordinate(1, 1), new Coordinate(2, 1) });
objectPaths.Add(new List<Coordinate>());
如果你想要一个更简洁的语法来指定代码中的路径,那么你可以考虑一个非常简单的类来表示一个路径。例如:
public class Path : List<Coordinate>
{
public Path() { }
public Path(params (int x, int y)[] coordinates) =>
AddRange(coordinates.Select(c => new Coordinate(c.x, c.y)));
}
公共类路径:列表
{
公共路径(){}
公共路径(参数(整数x,整数y)[]坐标)=>
AddRange(坐标。选择(c=>新坐标(c.x,c.y));
}
现在,您可以将路径集定义为:
var paths = new List<Path>();
paths.Add(new Path((0, 0), (0, 1), (1, 1), (2, 1)));
paths.Add(new Path((0, 1), (0, 1), (1, 1), (2, 1)));
paths.Add(new Path((1, 0), (0, 1), (1, 1), (2, 1)));
paths.Add(new Path());
var路径=新列表();
添加(新路径((0,0)、(0,1)、(1,1)、(2,1));
添加(新路径((0,1)、(0,1)、(1,1)、(2,1));
添加(新路径((1,0)、(0,1)、(1,1)、(2,1));
添加(新路径());
选择所需子集的语法与以前相同。因为这些都是path,并且总是有2个属性,您是否考虑过使用具有两个属性的坐标类?您的意思是像x[0][0]==0&&x[0][1]==1
?@NevilleNazerane如果有其他选项,这不是最好的选择,因为我已经在代码的其他部分使用了这个路径
列表
public struct Coordinate
{
public Coordinate(int x, int y)
{
X = x;
Y = y;
}
public int X { get; }
public int Y { get; }
public bool Equals(int x, int y) =>
X == x && Y == y;
}
var objectPaths = new List<List<Coordinate>>();
objectPaths.Add(new List<Coordinate> { new Coordinate(0, 0), new Coordinate(0, 1), new Coordinate(1, 1), new Coordinate(2, 1) });
objectPaths.Add(new List<Coordinate> { new Coordinate(0, 1), new Coordinate(0, 1), new Coordinate(1, 1), new Coordinate(2, 1) });
objectPaths.Add(new List<Coordinate> { new Coordinate(1, 0), new Coordinate(0, 1), new Coordinate(1, 1), new Coordinate(2, 1) });
objectPaths.Add(new List<Coordinate>());
objectPaths.Where(p => p.Count > 0 && (p[0].Equals(0, 0) || p[0].Equals(0, 1)));
public class Path : List<Coordinate>
{
public Path() { }
public Path(params (int x, int y)[] coordinates) =>
AddRange(coordinates.Select(c => new Coordinate(c.x, c.y)));
}
var paths = new List<Path>();
paths.Add(new Path((0, 0), (0, 1), (1, 1), (2, 1)));
paths.Add(new Path((0, 1), (0, 1), (1, 1), (2, 1)));
paths.Add(new Path((1, 0), (0, 1), (1, 1), (2, 1)));
paths.Add(new Path());