将二维数组上的两个循环转换为Linq语法

时间:2018-06-16 11:37:26

标签: c# arrays linq

我有一个包含MyObj类型对象的二维数组。

private MyObj[,] myObjs = new MyObj[maxX, maxY];

我希望在传入匹配对象时从数组中获取索引。我想从这个数组中获取x和y值。我可以将这两个值作为Position对象返回,该对象采用x和y坐标。

private Position GetIndices(MyObj obj)
{
    for (int x = 0; x < myObjs.GetLength(0); x++)
    {
        for (int y = 0; y < myObjs.GetLength(1); y++)
        {
            if (myObjs[x, y] == obj)
            {
                return new Position(x, y);
            }
        }
    }
}

是否可以将此代码缩短为某些Linq代码行?

3 个答案:

答案 0 :(得分:4)

但我不认为,它看起来不错:)

        var result = Enumerable.Range(0, myObjs.GetLength(0))
            .Select(x => Enumerable.Range(0, myObjs.GetLength(1)).Select(y => new { x, y }))
            .SelectMany(o => o)
            .FirstOrDefault(o => myObjs[o.x, o.y] == obj);

答案 1 :(得分:1)

如果您有兴趣,可以选择其他选项。它在第一个select中使用了一个索引器并进行了一些数学运算,以找到该索引在二维数组中的位置。

var o = new MyObj();

myObjs[1,2] = o;

var p = myObjs.Cast<MyObj>()
              .Select((x,i) => Tuple.Create(x,i))
              .Where(x => x.Item1 == o)
              .Select(x => new Point(x.Item2 / myObjs.GetLength(1), x.Item2 % myObjs.GetLength(1)))
              .SingleOrDefault();

Console.WriteLine(p);  // prints {X=1,Y=2}

看起来你看起来像是将x坐标视为数组的高度,y坐标是宽度,在这种情况下你想要稍微调整它:

var p = myObjs.Cast<MyObj>()
              .Select((x,i) => Tuple.Create(x,i))
              .Where(x => x.Item1 == o)
              .Select(x => new Point(x.Item2 % myObjs.GetLength(1), x.Item2 / myObjs.GetLength(1)))
              .SingleOrDefault();

Console.WriteLine(p);  // prints {X=2,Y=1}

我使用Point代替Position,因为它内置于.NET中,但您应该只能将一个交换为另一个。

答案 2 :(得分:0)

是的,这是可能的。您可以让Resharper为您完成工作(循环到linq)。安装完成后,just use the feature