糖衣阵列(动态调整大小并随机设置任何元素)
Sugar coated arrays (dynamically resizable and set any element at random)
我想要我的蛋糕并吃掉它。
我喜欢 C# 中的列表在超出数组初始容量时动态扩展的方式。然而,这还不够。我希望能够做这样的事情:
int[] n = new int[]; // Note how I'm NOT defining how big the array is.
n[5] = 9
是的,速度会有所牺牲,因为在幕后,.NET 需要检查是否超出了默认容量。如果有,那么它可以将数组扩展 5 倍左右。
不幸的是,对于列表,您并不是真的要设置任意元素,虽然如果您 do this 是可能的,但仍然不可能直接设置第五个元素,而不是最初设置列表的大小,更不用说尝试时动态扩展了。
对于任何解决方案,我都希望能够保持简单的方括号语法(而不是使用相对冗长的方法调用),并且速度相对较快(最好几乎与标准数组一样快)当它不扩展数组时。
请注意,我并不一定主张继承List,但如果你真的想要这样:
public class MyList<T> : List<T>
{
public T this[int i]
{
get {
while (i >= this.Count) this.Add(default(T));
return base[i];
}
set {
while (i >= this.Count) this.Add(default(T));
base[i] = value;
}
}
}
我要补充一点,如果您希望 "array" 的大部分值在程序的整个生命周期内保持为空,则使用 Dictionary<int, T>
会获得更高的效率,特别是随着 collection 的大小变大。
您可以在 List
上定义扩展方法:
public static class ExtensionMethods {
public static void Set<T>(this List<T> list, int index, T element) {
if (index < list.Count) {
list[index] = element;
} else {
for (int i = list.Count; i < index; i++) {
list.Add(default(T));
}
list.Add(element);
}
}
}
如果您希望第 12 个元素为 1024,请调用 list.Set(12, 1024)
。
这是你的圆周率
static public List<int> AddToList(int index,int value, List<int> input)
{
if (index >= input.Count)
{
int[] temparray = new int[index - input.Count + 1];
input.AddRange(temparray);
}
return (input[index] = value);
}
该问题的一个简单解决方案是从 Dictionary<TKey, TValue>
继承并仅使用值 generic:
public class MyCoolType<T> : Dictionary<int, T> { }
然后你就可以像这样使用它了:
MyCoolType<int> n = new MyCoolType<int>();
n[5] = 9;
还有关于性能的注释。
- 对于插入,这比列表快多,因为它不需要您调整大小或在数组中的任意位置插入元素。
List<T>
使用数组作为支持字段,当你调整它的大小时,它是昂贵的。 (编辑:列表有一个默认大小,您并不总是要调整它的大小,但是当您这样做时,它的成本很高)
- 对于查找,这非常接近 O(1) (source),因此与数组查找相当。列表的复杂度为 O(n),随着包含元素数量的增加,列表会逐渐变慢。
- 稀疏打包比使用密集打包的列表更节省内存,因为它不需要您使用空项目来达到特定索引。
其他注意事项:
- 在其他解决方案中,尝试在索引 570442959 处插入一个项目,例如,您将抛出
OutOfMemoryException
(在 32 位下,但即使是 64 位也有问题)。使用此解决方案,您可以使用 int
类型支持的任何可能的索引,最多 int.MaxValue
.
- 列表不允许负索引,这会。
- MyCoolType.Count相当于这里的数组
Length
属性。
以下是我的性能测试结果:
- 将 100 万个元素插入 MyList:29.4294424 秒
- 将 100 万个元素插入 CoolType:0.127499 秒
- 查找 100 万个随机元素 MyList:1.6330562 秒
- 查找 100 万个随机元素 CoolType:1.304348 秒
完整的测试来源:http://pastebin.com/kEdLgFaw
注意,对于 运行 这些测试,我必须设置为 X64 构建、调试,并且必须将以下内容添加到 app.config 文件中:
<runtime>
<gcAllowVeryLargeObjects enabled="true" />
</runtime>
我想要我的蛋糕并吃掉它。
我喜欢 C# 中的列表在超出数组初始容量时动态扩展的方式。然而,这还不够。我希望能够做这样的事情:
int[] n = new int[]; // Note how I'm NOT defining how big the array is.
n[5] = 9
是的,速度会有所牺牲,因为在幕后,.NET 需要检查是否超出了默认容量。如果有,那么它可以将数组扩展 5 倍左右。
不幸的是,对于列表,您并不是真的要设置任意元素,虽然如果您 do this 是可能的,但仍然不可能直接设置第五个元素,而不是最初设置列表的大小,更不用说尝试时动态扩展了。
对于任何解决方案,我都希望能够保持简单的方括号语法(而不是使用相对冗长的方法调用),并且速度相对较快(最好几乎与标准数组一样快)当它不扩展数组时。
请注意,我并不一定主张继承List,但如果你真的想要这样:
public class MyList<T> : List<T>
{
public T this[int i]
{
get {
while (i >= this.Count) this.Add(default(T));
return base[i];
}
set {
while (i >= this.Count) this.Add(default(T));
base[i] = value;
}
}
}
我要补充一点,如果您希望 "array" 的大部分值在程序的整个生命周期内保持为空,则使用 Dictionary<int, T>
会获得更高的效率,特别是随着 collection 的大小变大。
您可以在 List
上定义扩展方法:
public static class ExtensionMethods {
public static void Set<T>(this List<T> list, int index, T element) {
if (index < list.Count) {
list[index] = element;
} else {
for (int i = list.Count; i < index; i++) {
list.Add(default(T));
}
list.Add(element);
}
}
}
如果您希望第 12 个元素为 1024,请调用 list.Set(12, 1024)
。
这是你的圆周率
static public List<int> AddToList(int index,int value, List<int> input)
{
if (index >= input.Count)
{
int[] temparray = new int[index - input.Count + 1];
input.AddRange(temparray);
}
return (input[index] = value);
}
该问题的一个简单解决方案是从 Dictionary<TKey, TValue>
继承并仅使用值 generic:
public class MyCoolType<T> : Dictionary<int, T> { }
然后你就可以像这样使用它了:
MyCoolType<int> n = new MyCoolType<int>();
n[5] = 9;
还有关于性能的注释。
- 对于插入,这比列表快多,因为它不需要您调整大小或在数组中的任意位置插入元素。
List<T>
使用数组作为支持字段,当你调整它的大小时,它是昂贵的。 (编辑:列表有一个默认大小,您并不总是要调整它的大小,但是当您这样做时,它的成本很高) - 对于查找,这非常接近 O(1) (source),因此与数组查找相当。列表的复杂度为 O(n),随着包含元素数量的增加,列表会逐渐变慢。
- 稀疏打包比使用密集打包的列表更节省内存,因为它不需要您使用空项目来达到特定索引。
其他注意事项:
- 在其他解决方案中,尝试在索引 570442959 处插入一个项目,例如,您将抛出
OutOfMemoryException
(在 32 位下,但即使是 64 位也有问题)。使用此解决方案,您可以使用int
类型支持的任何可能的索引,最多int.MaxValue
. - 列表不允许负索引,这会。
- MyCoolType.Count相当于这里的数组
Length
属性。
以下是我的性能测试结果:
- 将 100 万个元素插入 MyList:29.4294424 秒
- 将 100 万个元素插入 CoolType:0.127499 秒
- 查找 100 万个随机元素 MyList:1.6330562 秒
- 查找 100 万个随机元素 CoolType:1.304348 秒
完整的测试来源:http://pastebin.com/kEdLgFaw
注意,对于 运行 这些测试,我必须设置为 X64 构建、调试,并且必须将以下内容添加到 app.config 文件中:
<runtime>
<gcAllowVeryLargeObjects enabled="true" />
</runtime>