Yan*_*hof 24 c# arrays list type-conversion
我有一个二维数组,我需要将其转换为List(相同的对象).我不想使用for或foreach循环来获取每个元素并将其添加到List.还有其他方法吗?
Jon*_*eet 56
好吧,你可以使用"blit"类型的副本,虽然它确实意味着制作一个额外的副本:(
double[] tmp = new double[array.GetLength(0) * array.GetLength(1)];
Buffer.BlockCopy(array, 0, tmp, 0, tmp.Length * sizeof(double));
List<double> list = new List<double>(tmp);
Run Code Online (Sandbox Code Playgroud)
如果您对单维数组感到满意,那么只需忽略最后一行:)
Buffer.BlockCopy被实现为我一个本地方法希望验证后使用极其高效复制.在List<T> constructor其中接受一个IEnumerable<T>是对于其中它实现的情况下最优化IList<T>,如double[]做.它将创建一个正确大小的后备数组,并要求它将自身复制到该数组中.希望这也会使用Buffer.BlockCopy或类似的东西.
这是三种方法的快速基准(for loop Cast<double>().ToList(),和Buffer.BlockCopy):
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
class Program
{
static void Main(string[] args)
{
double[,] source = new double[1000, 1000];
int iterations = 1000;
Stopwatch sw = Stopwatch.StartNew();
for (int i = 0; i < iterations; i++)
{
UsingCast(source);
}
sw.Stop();
Console.WriteLine("LINQ: {0}", sw.ElapsedMilliseconds);
GC.Collect();
GC.WaitForPendingFinalizers();
sw = Stopwatch.StartNew();
for (int i = 0; i < iterations; i++)
{
UsingForLoop(source);
}
sw.Stop();
Console.WriteLine("For loop: {0}", sw.ElapsedMilliseconds);
GC.Collect();
GC.WaitForPendingFinalizers();
sw = Stopwatch.StartNew();
for (int i = 0; i < iterations; i++)
{
UsingBlockCopy(source);
}
sw.Stop();
Console.WriteLine("Block copy: {0}", sw.ElapsedMilliseconds);
}
static List<double> UsingCast(double[,] array)
{
return array.Cast<double>().ToList();
}
static List<double> UsingForLoop(double[,] array)
{
int width = array.GetLength(0);
int height = array.GetLength(1);
List<double> ret = new List<double>(width * height);
for (int i = 0; i < width; i++)
{
for (int j = 0; j < height; j++)
{
ret.Add(array[i, j]);
}
}
return ret;
}
static List<double> UsingBlockCopy(double[,] array)
{
double[] tmp = new double[array.GetLength(0) * array.GetLength(1)];
Buffer.BlockCopy(array, 0, tmp, 0, tmp.Length * sizeof(double));
List<double> list = new List<double>(tmp);
return list;
}
}
Run Code Online (Sandbox Code Playgroud)
结果(以毫秒为单位的时间);
LINQ: 253463
For loop: 9563
Block copy: 8697
Run Code Online (Sandbox Code Playgroud)
编辑:更改了for循环以array.GetLength()在每次迭代时调用,for循环和块复制大约在同一时间进行.
nav*_*een 32
要转换double[,]成List<double>?如果你正在寻找一个单行,那么就去了
double[,] d = new double[,]
{
{1.0, 2.0},
{11.0, 22.0},
{111.0, 222.0},
{1111.0, 2222.0},
{11111.0, 22222.0}
};
List<double> lst = d.Cast<double>().ToList();
Run Code Online (Sandbox Code Playgroud)
Cod*_*aos 11
一个for循环是最快的方法.
您可以使用LINQ来完成它,但这会更慢.虽然你自己不编写循环,但仍然存在一个循环.
arr.SelectMany(x=>x).ToList().T[,]你可以简单地做arr.ToList()自IEnumerable<T>的T[,]二维数组中返回的所有元素.IEnumerable但不是IEnumerable<T>这样,你需要插入一个Cast<double>类似尚未建议的编码器.由于拳击,这将使它更慢.唯一可以使代码比朴素循环更快的是计算元素的数量并使用正确的容量构造List,因此它不需要增长.
如果您的阵列是矩形的,您可以获得大小width*height,使用锯齿状阵列可能会更难.
int width=1000;
int height=3000;
double[,] arr=new double[width,height];
List<double> list=new List<double>(width*height);
int size1=arr.GetLength(1);
int size0=arr.GetLength(0);
for(int i=0;i<size0;i++)
{
for(int j=0;j<size1;j++)
list.Add(arr[i,j]);
}
Run Code Online (Sandbox Code Playgroud)
从理论上讲,可能会使用私有反射和不安全的代码来使原始内存复制更快一些.但我强烈建议不要这样做.