【问题标题】:get partition ((N-1)-dimensional instance of the N-dimensional array) of a multidimensional array with LINQ使用 LINQ 获取多维数组的分区(N 维数组的 (N-1) 维实例)
【发布时间】:2013-03-21 19:26:11
【问题描述】:

我想从 3d 数组中获取 2d 数组。假设我有一个尺寸为 [10,10,10] 的双 3d 数组 A3
我需要得到一个二维数组 A2 = A3[:,5,:],即第二维的索引等于例如5.

如果我想获得二维数组 A2(即二维数组的一维实例)的分区(例如 A1=A2[2,:] 类型),我可以这样做(一维的索引设置为例如 2):

double[] A1 = Enumerable.Range(0,A2.Length).Select(x=>A2[2,x]).ToArray();

我怎样才能做到从 3 到 2(或通常从 N 到 N-1)维度?

编辑。示例输入:

double[,,] A3 = new double[2,3,4]{
            {
                {4,3,2,1},
                {5,4,3,2},
                {6,5,4,3}
            },
            {
                {1,2,3,4},
                {2,3,4,5},
                {3,4,5,6}
            }
        };

结果数组 A2=A3[:,1,:] 必须包含以下内容:{ {5,4,3,2},{2,3,4,5} }

【问题讨论】:

  • 您的分区大小是否相等,还是呈锯齿状?
  • 为什么需要 Linq?只需编写循环来完成它就会更容易加载(可能运行得更快)。只需编写一个扩展方法即可,Bob 就是你的叔叔!
  • 尺寸不相等,可能是[2,17,5];人们总是可以编写循环或函数而不是 LINQ。此外,假设知道如何完成这项任务,我可以轻松地将这种方法扩展到其他多维对象

标签: c# linq


【解决方案1】:

LINQ 通常不能很好地处理多维数组。这些操作本质上是一维的。它在嵌套的一维数组中表现得更好,所以如果你想返回一个深度为 2 的锯齿状数组,即 double[][] 而不是 double[,] LINQ 是更合适的工具。

public static T[][] GetPlane<T>(T[, ,] source, int secondDimensionValue)
{
    return Enumerable.Range(0, source.GetLength(0))
        .Select(i => Enumerable.Range(0, source.GetLength(2))
            .Select(j => source[i, secondDimensionValue, j])
            .ToArray())
        .ToArray();
}

【讨论】:

  • 是的,这就是我询问排名长度的原因 - 如果它们都相等,您可以在那里破坏 SelectMany + 偏移量计算
  • @JerKimball 请注意,即使维度的长度不相等,它也不是锯齿状数组。锯齿状数组是指单个维度的长度不是恒定的,这对于多维数组来说是可能的
  • 它有效,谢谢,你能告诉我如何将它作为 [,] 数组而不是 ("jagged"?) [][] 数组?
  • @MaxLi 到目前为止,最简单的方法是完全废弃 LINQ,只使用常规循环。在开始时创建合适大小的多维数组,有一个双for循环遍历变化的两个维度,然后在循环体中设置数组的相关值。
  • @MaxLi 而且您不会使用 LINQ 生成多维数组,因此可以选择返回不带 linq 的多维数组和带 LINQ 的锯齿状数组,我选择后者.
【解决方案2】:

这样的事情应该适用于 3->2:

static T[][] Collapse<T>(T[][][] array, int y)
{
  return
    Enumerable.Range(0, array.Length).Select(x =>
      Enumerable.Range(0, array[x][y].Length).Select(z =>
        array[x][y][z]
      ).ToArray()
   ).ToArray();
}

如何将此模式扩展到更高维度的问题应该是相当明显的。

编辑:

这以预期的方式扩展到多维数组。如果您对返回多维数组(而不是锯齿数组)感兴趣,LINQ 可能不是您想要用来解决此问题的工具,因为它没有提供明显或直观的方法来处理多维数组的创建。

如果您真的想要多维数组作为输出,我提供了一个示例“去毛刺”实现,它应该将其折叠回多维(非锯齿状)数组。

static T[][] Collapse<T>(T[,,] array, int y)
{
  return
    Enumerable.Range(0, array.GetLength(0)).Select(x =>
      Enumerable.Range(0, array.GetLength(2)).Select(z =>
        array[x,y,z]
      ).ToArray()
    ).ToArray();
}

static T[,] Deburr<T>(T[][] jagged)
{
  T[,] mArray = new T[jagged.Length, jagged.Max(array => array.Length)];

  foreach (int row in Enumerable.Range(0, jagged.Length))
    foreach (int col in Enumerable.Range(0, jagged[row].Length))
      mArray[row, col] = jagged[row][col];

  return mArray;
}

【讨论】:

  • 您能否将帖子编辑中的示例输入放入您的函数中?我将 [][][] 更改为 [,,] 等,但仍然无法运行
  • 我已更新答案以包含多维示例。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2018-09-18
  • 1970-01-01
  • 2011-05-10
  • 1970-01-01
  • 2016-05-28
相关资源
最近更新 更多