开发者

C#: Splicing array

Let's say I have a long[] called IDs with a few elements in the array.

What's the easiest way to splice into/insert a new element at a given index?

Right now I'm doing this, and I don't think it's optimal:

long[] IDs = ...;

var IDsList = IDs.ToList();
IDsList.Insert(newId, indexToIn开发者_如何学JAVAsertAt);

IDs = IDsList.ToArray();

There's nothing built-in into the Array class?! This strikes me as very odd, coming from the JavaScript world of [].splice().


Use a List<long> instead of the array since you're needing to make inserts.


It might seem a bit odd, but probably it was left out to prevent developers from writing code with bad performance too easily. (If you're inserting a new item in the middle, you probably want a resizable collection like List<T>.) The only way to "insert" into a fixed-size collection like an Array is to copy the collection's contents into a new collection and put the item there. Obviously this is not the best idea if you're performing a lot of insertions.

If the use of a T[] array is outside your control, and insertion is necessary, copying the array yourself is at least preferable to the code you have, as it saves you two costly operations: a copy and an insertion, which requires that potentially many elements be "shifted" by one index. (Your current solution copies the contents of the long[] into a List<long>, then inserts an item into that List<long>, then copies that List<long> back into a new long[].)

In this case (the choice of a T[] is not negotiable), you might consider an extension method to do what I just described above. This way at least you have a reusable piece of code for scenarios when you do need this behavior. Something like:

public static class ArrayHelper
{
    public static T[] Insert<T>(this T[] source, int index, T item)
    {
        if (source == null)
        {
            throw new ArgumentNullException("source");
        }

        if (index < 0 || index > source.Length)
        {
            throw new ArgumentOutOfRangeException("index");
        }

        // Allocate a new array with enough space for one more item.
        T[] result = new T[source.Length + 1];

        // Copy all elements before the insertion point.
        for (int i = 0; i < index; ++i)
        {
            result[i] = source[i];
        }

        // Insert the new value.
        result[index] = item;

        // Copy all elements after the insertion point.
        for (int i = index; i < source.Length; ++i)
        {
            result[i + 1] = source[i];
        }

        return result;
    }
}

Notice that the above is considerably more efficient than what you have now, as it only needs to perform the equivalent of a full array copy one time (not twice), and it also doesn't require any intermediate "shifting" of elements.

Usage:

int[] numbers = new int[] { 2, 3, 4 };
numbers = numbers.Insert(0, 1);

foreach (int number in numbers)
{
    Console.WriteLine(number);
}

Output:

1
2
3
4


Having to do something similar, here's what I've come up with, similar to Dan Tao's:

T[] newArr = new T[oldArr.Length+1];

//copy first part of the array, starting with newArr[0] <- oldArr[0], up to the insertion point
System.Array.Copy(oldArr, 0, newArr, 0, insertIndex, insertIndex);

//insert new element
newArr[insertIndex] = spliceElem;

//copy the rest of the array, from newArr[insert+1] <- oldArr[insert] to the end
System.Array.Copy(oldArr, insertIndex, newArr, insertIndex + 1, oldArr.Length-insertIndex);
return newArr;


You could try with

IDs.SetValue(newId, indexToInsertAt);

More here

0

上一篇:

下一篇:

精彩评论

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

最新问答

问答排行榜