开发者

How to efficiently resize an array of values, without boxing, used within a Dictionary<string, float[]>

In the code below, Pages is defined as

 public SortedDictionary<DateTime, float[]> Pages { get; set; }

I am trying to dynamically increase the size of this array. Can anyone tell how to increase the sized of the innermost float[]?

 var tt = currentContainer.Pages[dateTime];
 Array.Resize<float>(ref tt, currentContainer.Pages.Count + 1);

Fail 1

I tried the following code and get index out of range exception

    SortedDictionary<DateTime, float[]> Pages = new SortedDictionary<DateTime,float[]>();
    float[] xx = new float[1];
    xx[0] = 1;
    DateTime tempTime = DateTime.UtcNow;
    Pages.Add(tempTime, xx);
    var tt = Pages[tempTime];
    Array.Resize<float>(ref tt, Pages.Count + 1);
    Pages[tempTime][1] = 2;

Fail 2

The following gives a compile time error (property, index, or dynamic membe开发者_开发问答r can't be used as a ref value)

    SortedDictionary<DateTime, float[]> Pages = new SortedDictionary<DateTime,float[]>();
    float[] xx = new float[1];
    xx[0] = 1;
    DateTime tempTime = DateTime.UtcNow;
    Pages.Add(tempTime, xx);
    var tt = Pages[tempTime];
    // The line below is different from Fail 1 above ... compile time error
    Array.Resize<float>(ref Pages[tempTime], Pages.Count + 1);
    Pages[tempTime][1] = 2;

Question

What is the most performant answer to resize this array?

Would the answer change if it's likely that the final size will be 100-200 floats or 700-900 floats?

What if I change my allocation size from +1 to +128? .. or larger?


Use List<T>,

Example,

SortedDictionary<DateTime, List<float>> data;

data = new SortedDictionary<DateTime, List<float>>();

data.Add(DateTime.Now, new List<float>() { 11.4f, 322.3f, 33.5f });

EDIT:

How to get/set values from the list?

List<float> a = new List<float>()
{
  10.2f,20.3f
};

float v1 = a[0];
float v2 = a[1];

Console.WriteLine("{0} {1}", v1, v2);

a[0] = 90.40f;
Console.WriteLine("{0} {1}", a[0],a[1]);


First, do consider using a Dictionary<DateTime, List<Float>>, instead of the array. Since your code examples all involved expanding the array size by 1, that implies to me that you're going to resize the arrays many times to get to their final size. If that's the case, then choosing a container that can expand on its own, and can do so efficiently, is going to be better.

Second, all your examples are using array lengths one greater than the number of items in the dictionary. That's an unusual relationship, are you sure that a Dictionary<DateTime, (some group of floats)> is the proper container?

That said, here's how to resize the array inside a Dictionary.

SortedDictionary<DateTime, float[]> Pages = new SortedDictionary<DateTime,float[]>();
DateTime date = DateTime.UtcNow;

float[] arr = Pages[date];
Array.Resize<float>(ref arr, arr.Length + 1);
Pages[date] = arr; // [] overwrites the old value, unlike Add().


Array.Resize(ref tt, Pages.Count + 1); Pages[tempTime] = tt;


Instead of

public SortedDictionary< DateTime, float[]> Pages { get; set; },

you could use

public SortedDictionary< DateTime, List< float>> Pages { get; set; },

so you won't have to resize and if you still want to access it as an array, you can always use the ToArray() of the List class.

Hope this helps


I would use a List as suggested in the other answers. The reason you can't change the array with Array.Resize() is that it copies the array into a new array, for which it returns the reference for (Reflector output below) - so unless you re-assign the new value to Pages[tempTime] you are out of luck.

[ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
public static void Resize<T>(ref T[] array, int newSize)
{
    if (newSize < 0)
    {
        throw new ArgumentOutOfRangeException("newSize", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
    }
    T[] sourceArray = array;
    if (sourceArray == null)
    {
        array = new T[newSize];
    }
    else if (sourceArray.Length != newSize)
    {
        T[] destinationArray = new T[newSize];
        Copy(sourceArray, 0, destinationArray, 0, (sourceArray.Length > newSize) ? newSize : sourceArray.Length);
        array = destinationArray;
    }
}
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜