如果您打算使用当前的数据结构,那么您可以这样做,但语法不会很漂亮。这基本上就像 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
那么从 (0, 0) 或 (0, 1) 开始的路径子集是:
arrayPaths.Where(p =>
p.GetUpperBound(0) >= 0 &&
p.GetUpperBound(1) >= 1 &&
(
(p[0, 0] == 0 && p[0, 1] == 0) ||
(p[0, 0] == 0 && p[0, 1] == 1)
));
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>());
现在您感兴趣的路径子集是:
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());
并且选择你想要的子集的语法和以前一样。