我正在处理bool
,int
和各种struct
的多维数组。代码循环遍历这些数组并对特定值执行某些操作。例如,
for (int x = 0; x < this.Size.Width; x++) {
for (int y = 0; y < this.Size.Height; y++) {
if (this.Map[x, y]) {
DrawTerrain(this.Tile[x, y].Location, Terrain.Water);
}
}
}
我可以做简单的LINQ,但我不能做我想做的事情。我想做的是使用LINQ。也许像是
from x in this.Map where x == true execute DrawTerrain(...)
但是,我不明白如何获取x和y位置或如何在LINQ语句中调用方法。
另外,如果我可以将此代码放入函数并且能够使用委托或谓词调用它,那将会很棒吗?我不知道委托或谓词是否正确。
void Draw(Delegate draw, bool[,] map, struct[,] tiles)
from x in map where x == true draw(titles[x,y]).invoke;
}
答案 0 :(得分:1)
嗯,如果你努力工作,你可以用LINQ来做,但这会很痛苦。听起来你的第一段代码绝对没问题。
有一个通用的版本来采取行动似乎非常合理:
public delegate void Drawer(int x, int y, Tile tile);
public void Draw(Drawer drawer, bool[,] map, Tile[,] tiles) {
for (int x = 0; x < this.Size.Width; x++) {
for (int y = 0; y < this.Size.Height; y++) {
if (this.Map[x, y]) {
drawer(x, y, tiles[x, y]);
}
}
}
}
如果真的想要LINQ版本,那就是:
var query = from x in Enumerable.Range(0, Size.Width)
from y in Enumerable.Range(0, Size.Height)
where Map[x, y]
select new { x, y };
foreach (var pair in query)
{
DoWhatever(pair.x, pair.y, tiles[pair.x, pair.y]);
}
答案 1 :(得分:1)
您可以执行以下Linq查询以获取x,y值,然后迭代它们以运行您的方法。
var points = from x in Enumerable.Range(0, this.Size.Width - 1)
from y in Enumerable.Range(0, this.Size.Width - 1)
where this.Map[x, y]
select new { X = x, Y = y };
foreach (var p in points)
DrawTerrain(this.Tile[p.X, p.Y].Location, Terrain.Water);
答案 2 :(得分:1)
LINQ查询语法并非真正用于处理二维数据结构,但您可以编写一个扩展方法,将2D数组转换为包含原始2D数组中坐标的值序列。数组中的值。您需要一个帮助程序类型来存储数据:
class CoordinateValue<T> {
public T Value { get; set; }
public int X { get; set; }
public int Y { get; set; }
}
然后你可以编写扩展方法(对于任何2D数组),如下所示:
IEnumerable<CoordinateValue<T>> AsEnumerable(this T[,] arr) {
for (int i = 0; i < arr.GetLength(0); i++)
for (int j = 0; j < arr.GetLength(0); j++)
yield new CoordinateValue<T> { Value = arr[i, j]; X = i; Y = j; };
}
现在你终于可以开始使用LINQ了。要获取2D数组中所有元素的坐标,使得元素中存储的值为true
,您可以使用以下内容:
var toDraw = from tile in this.Map.AsEnumerable()
where tile.Value == true
select tile;
// tile contains the coordinates (X, Y) and the original value (Value)
foreach(var tile in toDraw)
FillTile(tile.X, tile.Y);
这使您可以在过滤切片时指定一些有趣的条件。例如,如果您只想获得对角元素,可以写:
var toDraw = from tile in this.Map.AsEnumerable()
where tile.Value == true && tile.X == tile.Y
select tile;
回答第二个问题 - 如果要将行为封装到方法中,您可能需要使用一些Action<...>
委托来表示将传递给方法的绘图函数。这取决于绘图方法的类型签名。