我有以下课程
class Tile
{
public int height;
public int terrain;
}
我有一个Tiles的二维数组
Tile[,] area = new Tile[5,5];
如何将我的区域从Tile[,]
映射到int[,]
,只保存高度?
我试过这样做:
area.Select(tile => tile.height)
但显然C#多维数组没有实现IEnumerable。
我怎么能解决这个问题?
答案 0 :(得分:6)
我怎么能解决这个问题?
通过编写代码。没有“选择”可行,所以自己做:
static class Extensions
{
public static R[,] Select<T, R>(this T[,] items, Func<T, R> f)
{
int d0 = items.GetLength(0);
int d1 = items.GetLength(1);
R[,] result = new R[d0, d1];
for (int i0 = 0; i0 < d0; i0 += 1)
for (int i1 = 0; i1 < d1; i1 += 1)
result[i0, i1] = f(items[i0, i1]);
return result;
}
现在你有了你想要的扩展方法。
练习:
答案 1 :(得分:1)
如果你真的,实际上,只是想要,你可以构建这样的东西:
public static void Main(string[] args)
{
var area = new Tile[5, 5];
for (var j = 0; j < 5; j++)
for (var i = 0; i < 5; i++)
area[i, j] = new Tile() { height = (j + 1) * (i + 1), terrain = 99 };
你的linq:
// this copies the data over from your area-array into a new int[5,5] array using
// IEnumerable.Aggregate(...) with an emtpy seeded int[5,5] array and
// leverages Enumerable.Range() with integer division + modular to get
// the indices right
var onlyHeights = Enumerable
.Range(0, 25)
.Aggregate(new int[5, 5], (acc, i) =>
{
acc[i / 5, i % 5] = area[i / 5, i % 5].height;
return acc;
});
测试:
for (var j = 0; j < 5; j++)
for (var i = 0; i < 5; i++)
Console.WriteLine($"area.height {area[i, j].height} => {onlyHeights[i, j]}");
Console.ReadLine();
}
输出:
area.height 1 => 1
area.height 2 => 2
area.height 3 => 3
area.height 4 => 4
area.height 5 => 5
area.height 2 => 2
area.height 4 => 4
area.height 6 => 6
area.height 8 => 8
area.height 10 => 10
area.height 3 => 3
area.height 6 => 6
area.height 9 => 9
area.height 12 => 12
area.height 15 => 15
area.height 4 => 4
area.height 8 => 8
area.height 12 => 12
area.height 16 => 16
area.height 20 => 20
area.height 5 => 5
area.height 10 => 10
area.height 15 => 15
area.height 20 => 20
area.height 25 => 25
但这只是伪装的一些嵌套for's
。
答案 2 :(得分:1)
由于没有开箱即用的方法,您可以尝试这里提出的解决方法:
从原始帖子中提取,所有信用均转到原始海报:Enumerating on Multi-dimentional arrays
public static class ArrayExtensions
{
public static IEnumerable<T> ToEnumerable<T>(this Array target)
{
foreach (var item in target)
yield return (T)item;
}
}
答案 3 :(得分:1)
如果你想要一个更通用的LINQ类方法接受更高维数组。
public static class ArrayExtensions
{
private static IEnumerable<int[]> CreatePermutations(int[] lengths, int pos = 0)
{
for (var i = 0; i < lengths[pos]; i++)
{
var newArray = (int[])lengths.Clone();
newArray[pos] = i;
if (pos + 1 >= lengths.Length)
{
yield return newArray;
continue;
}
foreach (var next in CreatePermutations(newArray, pos + 1)) yield return next;
}
}
public static Array Select<T,P>(this Array target, Func<T, P> func)
{
var dimensions = target.Rank;
var lengths = Enumerable.Range(0, dimensions).Select(d => target.GetLength(d)).ToArray();
var array = Array.CreateInstance(typeof(P), lengths);
var permutations = CreatePermutations(lengths);
foreach (var index in permutations)
{
array.SetValue(func((T)target.GetValue(index)), index);
}
return array;
}
}
你可以称之为。
var heightOnly = area.Select<Tile, int>(a => a.height);