如何从IEnumerable创建多维数组

时间:2018-08-08 16:18:30

标签: c# multidimensional-array ienumerable

是否有一些优雅的方法可以从IEnumerable创建多维数组。我知道怎么写这样的函数

program holler
   use ISO_FORTRAN_ENV
   integer(INT32) ID
! holler.txt should exist in the current directory
! and contain at least 4 characters
   open(10,file='holler.txt',status='old')
   read(10,'(A4)') ID
!   write(*,'(*(g0))') 'ID == 4HEOT  = ',ID == 4HEOT ! Fails
!   write(*,'(*(g0))') 'ID == 4HEOT  = ',ID == int(4HEOT ,KIND(ID)) ! Fails
   write(*,'(*(g0))') 'ID == 4HEOT  = ',ID == transfer(4HEOT ,ID) ! Success
   BLOCK
      integer(kind(ID)) compare
      compare = 4HEOT ! Note trailing space
      write(*,'(*(g0))') 'ID == 4HEOT  = ',ID == compare ! Success
   END BLOCK
end program holler

看起来不太好。做到这一点的一种优雅方法是:

double[,] GetMultidimesionalArray(IEnumerable<double> ienumerable, int nRows, int nColumns)
{
   var toReturn = new double[nRows,nColumns];
   var e = ienumerable.Select((x, i) => new { el = x, id = i });
   foreach (var item in e)
      toReturn[item.id / nColumns, item.id % nColumns] = item.el;
   return toReturn;
}

但这不是很好,因为在内存中创建了附加数组(ienumerable.ToArray())。

因此,我正在寻找一种解决问题的优雅方法(就像第二种方法一样),而且在时间/内存方面也很有效。

1 个答案:

答案 0 :(得分:1)

不幸的是,LINQ不能直接处理2D数组,因此如果您坚持使用double[,]返回类型,则需要循环。您的方法很好;一种替代方法是使用两个嵌套循环来避免使用除法和取模来计算索引:

double[,] GetMultidimesionalArray(IEnumerable<double> ienumerable, int nRows, int nColumns) {
    var res = new double[nRows,nColumns];
    using (var iter = ienumerable.GetEnumerator()) {
        for (var r = 0 ; r != nRows ; r++) {
            for (var c = 0 ; c != nColumns; c++) {
                if (!iter.MoveNext()) {
                    break;
                }
                res[r,c] = iter.Current;
            }
        }
    }
   return res;
}

与nRows×nColumns的预期大小相比,序列中元素太多或太少时,此方法不会引发异常。此外,其代码结构反映了返回值的结构(即,两个嵌套循环填充2D数组),这使代码更易于理解。