簡體   English   中英

使用LINQ從多維數組中提取特定值

[英]Using LINQ to Extract Specific Values from Multi-Dimensional Array

我正在使用boolint和各種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;
    }

好吧,如果你努力工作,你可以用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]);
}

您可以執行以下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);

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<...>委托來表示將傳遞給方法的繪圖函數。 這取決於繪圖方法的類型簽名。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM