Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/310.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何在C#中快速将二维阵列转换为一维阵列?_C#_Arrays - Fatal编程技术网

如何在C#中快速将二维阵列转换为一维阵列?

如何在C#中快速将二维阵列转换为一维阵列?,c#,arrays,C#,Arrays,我有一个多维double[,]数组,它的大小是[1,N](假设N是已知的)。将其转换为长度为N的一维double[]数组的最快方法是什么 我是C#新手,我用它与Matlab函数交互。我使用的Matlab函数返回1-D行向量。在C中,它被视为对象[,],我只能将其转换为双[,]。但是,我需要它的类型为double[],作为另一个函数的输入。有没有一种快速的方法可以将这个二维双数组转换为具有相同元素和相同顺序的一维数组 我需要转换尽可能快,因为我正在处理实时应用程序。最快的方法是直接内存复制方法之一

我有一个多维
double[,]
数组,它的大小是[1,N](假设N是已知的)。将其转换为长度为N的一维
double[]
数组的最快方法是什么

我是C#新手,我用它与Matlab函数交互。我使用的Matlab函数返回1-D行向量。在C中,它被视为
对象[,]
,我只能将其转换为
双[,]
。但是,我需要它的类型为
double[]
,作为另一个函数的输入。有没有一种快速的方法可以将这个二维双数组转换为具有相同元素和相同顺序的一维数组


我需要转换尽可能快,因为我正在处理实时应用程序。

最快的方法是直接内存复制方法之一,如,或

示例

var ary1 = new int[3,3];
ary1[0, 0] = 0;
ary1[0, 1] = 1;
ary1[0, 2] = 2;
ary1[1, 0] = 3;
ary1[1, 1] = 4;
ary1[1, 2] = 5;
ary1[2, 0] = 6;
ary1[2, 1] = 7;
ary1[2, 2] = 8;

var ary2 = new int[9];

Buffer.BlockCopy(ary1, 0, ary2, 0, 9 * sizeof(int));

Console.WriteLine(string.Join(",", ary2));
输出

0,1,2,3,4,5,6,7,8
您也可以使用
memcpy
,但是您将从PInvoke中产生初始开销

[DllImport("msvcrt.dll", EntryPoint = "memcpy", CallingConvention = CallingConvention.Cdecl, SetLastError = false)]
public static extern IntPtr memcpy(IntPtr dest, IntPtr src, UIntPtr count);
基准 基准测试运行100次,每次运行后垃圾收集,并相互验证准确性,结果从最快运行的前75%进行整理,刻度是多维数组的维度长度,即
double[scale,scale]

┌──────────────────┬────────────────────────────────────────────┐
│        Test Mode │ Release (64Bit)                            │
│   Test Framework │ .NET Framework 4.7.1 (CLR 4.0.30319.42000) │
╞══════════════════╪════════════════════════════════════════════╡
│ Operating System │ Microsoft Windows 10 Pro                   │
│          Version │ 10.0.17763                                 │
├──────────────────┼────────────────────────────────────────────┤
│       CPU System │ Intel(R) Core(TM) i7-7700 CPU @ 3.60GHz    │
│  CPU Description │ Intel64 Family 6 Model 158 Stepping 9      │
├──────────────────┼──────────┬──────────────────┬──────────────┤
│  Cores (Threads) │ 4 (8)    │     Architecture │ x64          │
│      Clock Speed │ 3600 MHz │        Bus Speed │ 100 MHz      │
│          L2Cache │ 1 MB     │          L3Cache │ 8 MB         │
└──────────────────┴──────────┴──────────────────┴──────────────┘
字节数组的结果 双数组的结果 测试代码
[测试(“块拷贝”,“真”)
公共双[]测试1(双[,]输入,整数刻度)
{
var width=input.GetLength(0);
变量高度=输入.GetLength(1);
变量大小=宽度*高度;
var结果=新的双[大小];
BlockCopy(输入,0,结果,0,大小*sizeof(双精度));
返回结果;
}
[测试(“MarshallCopy”、“false”)
公共不安全双[]测试2(双[,]输入,整数刻度)
{
var width=input.GetLength(0);
变量高度=输入.GetLength(1);
变量大小=宽度*高度;
var结果=新的双[大小];
固定(双*输入=输入)
封送处理副本((IntPtr)pInput,结果,0,大小);
返回结果;
}
[测试(“电子副本”,“假”)
公共双[]测试3(双[,]输入,整数刻度)
{
var width=input.GetLength(0);
变量高度=输入.GetLength(1);
变量大小=宽度*高度;
var结果=新的双[大小];
对于(变量i=0;i

注意:您可能应该自己在自己的spec PC、框架等上运行这些测试,并且应该仅用作指南

我刚开始考虑锯齿阵列,所以这个问题看起来太简单了:)但是,使用2D阵列也不难:

using System.Linq;

var twoDArray = new double[1,5] { { 1, 2, 3, 4, 5 } };
var oneDArray = twoDArray.OfType<double>().ToArray();
// oneDArray == { 1, 2, 3, 4, 5 }
使用System.Linq;
var twoDArray=新的双[1,5]{{1,2,3,4,5};
var oneDArray=twoDArray.OfType().ToArray();
//oneDArray=={1,2,3,4,5}
它还可用于任何尺寸的二维阵列:

var twoDArray2 = new double[2,3] { { 1, 2, 3 }, { 4, 5, 6 } };
var oneDArray2 = twoDArray2.OfType<double>().ToArray();
// oneDArray2 == { 1, 2, 3, 4, 5, 6 }
var twodaray2=新的双[2,3]{{1,2,3},{4,5,6};
var oneDArray2=twoDArray2.OfType().ToArray();
//oneDArray2=={1,2,3,4,5,6}
关于表演的抒情离题:

当然,LINQ比直接内存操作慢(多得多)。但是您应该记住,LINQ(以及
C#
也一样)不是关于“执行时间优化”,而是关于“开发便利性”。所以对我来说,易读的单线LINQ表达式比快速内存操作魔术更可取,即使它将
double[165535]
转换为
double[65535]
的时间为35.116µs,而不是7.402 ms


C#
由于其受管理的性质,速度较慢,因此如果您需要运行速度极快的算法,我建议您切换到
C++

二维数组的大小为(1,N)。假设一维数组在第一维度中有[1,2,3,4],在第二维度中没有其他内容,则一维数组也将是相同的[1,2,3,4]。但是它将是一个长度为N的双[]数组,而不是大小为(1,N)的双[,]数组。@vasily.sib您自己试试,看看为什么不可以;)是的,不是参差不齐的数组。我只是想知道你用哪种工具来构建这么好看的表格?@shingo我有一个盒子和表格绘图库,它可以用benchmarker工具编写的那些奇特的东西,我会把它扔到github上,等我有机会对它进行一次彻底的清理,我真的同意,我把另一个答案标记为解决方案,因为从技术上讲,这是我最初问题的准确答案,也是一个很好的答案。然而,我承认优化与便利的权衡,我最终在我的C#app中使用了这个答案。同时,我已经在把所有东西移植到C++中,用于运行更快的算法。
[Test("BlockCopy", "", true)]
public double[] Test1(double[,] input, int scale)
{
   var width = input.GetLength(0);
   var height = input.GetLength(1);
   var size = width * height;
   var result = new double[size];
   Buffer.BlockCopy(input, 0, result, 0, size * sizeof(double));
   return result;
}

[Test("MarshalCopy", "", false)]
public unsafe double[] Test2(double[,] input, int scale)
{
   var width = input.GetLength(0);
   var height = input.GetLength(1);
   var size = width * height;
   var result = new double[size];
   fixed (double* pInput = input)
      Marshal.Copy((IntPtr)pInput, result, 0, size );
   return result;
}

[Test("ElemCopy", "", false)]
public double[] Test3(double[,] input, int scale)
{
   var width = input.GetLength(0);
   var height = input.GetLength(1);
   var size = width * height;

   var result = new double[size];
   for (var i = 0; i < width; i++)
      for (var j = 0; j < height; j++)
         result[i * height + j] = input[i,j];
   return result;
}
[Test("ElemCopy Unsafe", "", false)]
unsafe public double[] Test4(double[,] input, int scale)
{
   var width = input.GetLength(0);
   var height = input.GetLength(1);
   var size = width * height;

   var result = new double[size];
   fixed (double* pInput = input, pResult = result)
      for (var i = 0; i < width; i++)
         for (var j = 0; j < height; j++)
            *(pResult + i * height + j) = *(pInput + i * height + j);
   return result;
}
[Test("memcpy", "", false)]
unsafe public double[] Test5(double[,] input, int scale)
{
   var width = input.GetLength(0);
   var height = input.GetLength(1);
   var size = width * height;

   var result = new double[size];
   fixed (double* pInput = input, pResult = result)
      memcpy((IntPtr)pResult, (IntPtr)pInput, (UIntPtr)(size * sizeof(double)));
   return result;
}
[Test("Linq", "", false)]
unsafe public double[] Test6(double[,] input, int scale)
{
   return input.OfType<double>().ToArray();
}
using System.Linq;

var twoDArray = new double[1,5] { { 1, 2, 3, 4, 5 } };
var oneDArray = twoDArray.OfType<double>().ToArray();
// oneDArray == { 1, 2, 3, 4, 5 }
var twoDArray2 = new double[2,3] { { 1, 2, 3 }, { 4, 5, 6 } };
var oneDArray2 = twoDArray2.OfType<double>().ToArray();
// oneDArray2 == { 1, 2, 3, 4, 5, 6 }