James Ko
James Ko

Reputation: 34569

Best way to copy over items to a List partially?

Let's say you have two arrays, src and dest. dest is bigger. You want to copy over all the elements from src to the beginning of dest and overwrite anything that may already be there. To do this, we can do an Array.Copy(src, dest, src.Length), which is both more concise and more efficient than a for loop.

Now, say dest becomes a List<T>. What's the most efficient way to copy all of the elements from src? I know List is internally implemented using an array, so if we could get our hands on that (barring reflection, of course) we could just do an Array.Copy and this would be a non-issue.

I'm not looking for a for-loop because of said reasons, but if that's the only way to do it I guess that'll have to do.


Edit: I was hoping not to have to type up a code sample on my phone, but it seems from the barrage of incorrect answers I'm going to have to:

int[] src = { 1, 2, 3 };
var dest = new List<int>() { 4, 5, 6, 7 };

for (int i = 0; i < src.Length; i++)
{
    dest[i] = src[i];
}

What I'm looking for would be the logical equivalent of the above, but have the performance of Array.Copy.

Upvotes: 2

Views: 152

Answers (6)

bb441db
bb441db

Reputation: 294

Just compared your function with the Array.Copy() function.

//values used for the benchmark
int[] src = { 1, 2, 3 };
int[] destArray = { 4, 5, 6, 7 };
var destList = new List<int>() { 4, 5, 6, 7 };

//Array.Copy() test : avarage 1004 ms
for (int i = 0; i < 20000000; i++)
{
    Array.Copy(src, destArray, src.Length);
}
//Your solution test : avarage 634 ms
for (int i = 0; i < 20000000; i++)
{
    Copy(src, destList, src.Length);
}

public void Copy(int[] sourceArray, List<int> destinationList, int length)
{
    for (int i = 0; i < length; i++)
    {
        destinationList[i] = sourceArray[i];
    }
}

*these results are the avarage of 20 benchmarks.

Upvotes: 0

Deepak Bhatia
Deepak Bhatia

Reputation: 1100

I think you are looking for something like this:

int[] desta = (int[]) typeof(List<int>)
               .GetField("_items", BindingFlags.NonPublic |     BindingFlags.Instance)
               .GetValue(dest);
Array.Copy(src, desta, src.Length)

Upvotes: 1

Devenias
Devenias

Reputation: 31

To achieve the same result as Array.Copy I would use

var src = new int[] { 50, 51, 52, 53, 54, 55 };
var dest = new List<int> { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12 };

dest.RemoveRange(0, src.Length);
dest.InsertRange(0, src);

// dest: [ 50, 51, 52, 53, 54, 55, 7, 8, 9, 10, 11, 12 ]

Edit: This method is about 7 times slower than Array.Copy, but for large Arrays much faster than to loop through the array. If you have smal source arrays, a loop may be the best choice.

Upvotes: 1

Yang Zhang
Yang Zhang

Reputation: 4570

If your src is a list, another option is to use ForEach defined in List, I believe the performance is similar to Array.Copy

dest = new List<T>();
src.ForEach(item => dest.Add(item));

If you need value copy, you can write this:

src.ForEach(item => dest.Add(item.Clone()));

In this case, just need to make sure item is ICloneable.

Upvotes: 0

Code.me
Code.me

Reputation: 281

You can also do

int[] src = new int[] {1, 2, 3};

List<int> dest = new List<int>(src);

Upvotes: 0

Rahul
Rahul

Reputation: 77896

Why can't you just call ToList() on src array which will Create a List<int> from int[]. A small sample

        int[] src = new int[] { 1,2,3,4,5,6,7,8,44,555,45,654};
        List<int> dest = src.ToList();

Upvotes: 0

Related Questions