使用LINQ在2维矩阵中获取所有对角线

时间:2017-02-11 05:00:09

标签: c# arrays linq matrix

给出下面的二维矩阵

int[][] m = new int[][] {   new int[] { 1, 2, 3, 4 },
                            new int[] { 0, 1, 4, 3 },
                            new int[] { 4, 0, 2, 2 },
                            new int[] { 4, 2, 0, 1 }};

我想使用LINQ获取所有对角线,即

4 3 3 2 4 2 1 1 2 1 0 0 0 4 2 4

现在我正在使用两个丑陋的for循环,但我知道必须有一个更好的方法。

List<List<int>> e = new List<List<int>>();
for (int i = 0; i < m.Count(); i++)
{
    for (int j = m.Count() - 1; j >= 0; j--)
    {
        if (i == 0 || (i > 0 && j == 0))
        {
            e.Add(new List<int> { m[i][j] });
        }

        if (i > 0 && j > 0)
        {
            e[i - j + m.Count() - 1].Add(m[i][j]);
        }
    }
}

2 个答案:

答案 0 :(得分:0)

使用LINQ

据我所知,这个特殊问题并没有真正从使用LINQ中获得任何性能优势。也许你可以进一步解释这个要求,因为性能损失和增加的复杂性似乎不会导致你当前或任何其他解决方案更加“优雅”的解决方案,只能实现迭代方法解决问题。

替代方案:使用Math.Abs​​方法

我认为使用Math.Abs()会为您提供有效的循环

int length = 4;
for (int i = -length; i <= Math.Abs(length); i++)
{
    Console.WriteLine(i);
    // -4, -3, -2, -1,  0, +1, +2, +3, +4
}

这可能是使用Math.Abs()的潜在解决方案。它在通过中心对角线时反转顺序。

int[][] m = new int[][] {
    new int[] { 1, 2, 3, 4 },
    new int[] { 0, 1, 4, 3 },
    new int[] { 4, 0, 2, 2 },
    new int[] { 4, 2, 0, 1 }};

int max = m.Length;
for (int i = -max+1; Math.Abs(i) < max; i++)
{
    for (int j = 0; j <= max - Math.Abs(i) - 1; j++)
    {
        int row = i < 0 ? j : i + j;
        int col = i > 0 ? j : (Math.Abs(i) + j);
        Console.Write(m[row][col]);
    }
    Console.WriteLine();
}

答案 1 :(得分:0)

展平矩阵,然后按创建的键分组:

var d = m.SelectMany((row, rowIdx) =>
        row.Select((x, colIdx) => new { Key = rowIdx - colIdx, Value = x }))
    .GroupBy(x => x.Key, (key, values) => values.Select(i => i.Value).ToArray())
    .ToArray();

如果对角线需要符合逻辑顺序,还需要对结果进行排序:

var d2 = m.SelectMany((row, rowIdx) => 
         row.Select((x, colIdx) => new { Key = rowIdx - colIdx, Value = x }))
    .GroupBy(x => x.Key)
    .OrderBy(x => x.Key)
    .Select(values => values.Select(i => i.Value).ToArray())
    .ToArray();