我想要通过0.0初始化一个长度为N的对象列表。我的想法是这样的:
var TempList = new List<float>(new float[(int)(N)]);
有更好(更有效)的方法来做这件事吗?
我想要通过0.0初始化一个长度为N的对象列表。我的想法是这样的:
var TempList = new List<float>(new float[(int)(N)]);
有更好(更有效)的方法来做这件事吗?
您目前的解决方案是创建一个数组,其唯一目的是将列表初始化为零,然后丢弃该数组。这可能看起来不高效。但是,正如我们所看到的,实际上非常有效!
这里有一种不创建中间数组的方法:
int n = 100;
var list = new List<float>(n);
for (int i = 0; i < n; ++i)
list.Add(0f);
另外,您还可以使用Enumerable.Repeat()
提供0f
“n”次,方法如下:
var list = new List<float>(n);
list.AddRange(Enumerable.Repeat(0f, n));
但这两种方法都被证明速度较慢!
这里有一个小测试应用程序来做一些计时。
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
namespace Demo
{
public class Program
{
private static void Main()
{
var sw = new Stopwatch();
int n = 1024*1024*16;
int count = 10;
int dummy = 0;
for (int trial = 0; trial < 4; ++trial)
{
sw.Restart();
for (int i = 0; i < count; ++i)
dummy += method1(n).Count;
Console.WriteLine("Enumerable.Repeat() took " + sw.Elapsed);
sw.Restart();
for (int i = 0; i < count; ++i)
dummy += method2(n).Count;
Console.WriteLine("list.Add() took " + sw.Elapsed);
sw.Restart();
for (int i = 0; i < count; ++i)
dummy += method3(n).Count;
Console.WriteLine("(new float[n]) took " + sw.Elapsed);
Console.WriteLine("\n");
}
}
private static List<float> method1(int n)
{
var list = new List<float>(n);
list.AddRange(Enumerable.Repeat(0f, n));
return list;
}
private static List<float> method2(int n)
{
var list = new List<float>(n);
for (int i = 0; i < n; ++i)
list.Add(0f);
return list;
}
private static List<float> method3(int n)
{
return new List<float>(new float[n]);
}
}
}
以下是我在 RELEASE 构建中的结果:
Enumerable.Repeat() took 00:00:02.9508207
list.Add() took 00:00:01.1986594
(new float[n]) took 00:00:00.5318123
private static List<float> method4(int n)
{
var list = new List<float>(n);
list.GetType().GetField("_size", BindingFlags.NonPublic | BindingFlags.Instance).SetValue(list, n);
return list;
}
这样做可以将时间缩短到不到十分之一秒,相比下一个最快的方法要快一半。但是不要这样做。
Enumerable.Repeat
并不是一个好的替代方案,因为这样列表就无法知道大小,所以必须枚举序列并经常调整内部数组的大小。 - Tim SchmelterEnumerable.Repeat()
这个的确说得好!为了好玩,我正在做一些计时。:) - Matthew WatsonEnumerable.Range
的,但同样适用于Enumerable.Repeat
。 - Tim Schmeltervar itemsWithZeros = new float[length];
这是什么问题
float[] A = new float[N];
或者
List<float> A = new List<float>(N);
List<float>
的解决方案会产生一个空列表,只有内部的N
项被初始化。因此,我们可以通过一些反射技巧来欺骗它。 static void Main(string[] args)
{
int N=100;
float[] array = new float[N];
List<float> list=new List<float>(N);
var size=typeof(List<float>).GetField("_size", BindingFlags.Instance|BindingFlags.NonPublic);
size.SetValue(list, N);
// Now list has 100 zero items
}
Count == 0
的列表。 - Matthew Watson
float
的默认值,因此您不需要执行任何其他初始化步骤。 - Brett Wolfingtonfloat[]
。 - John Alexiou