1

I have an array with total 5000 elements and at one functionality, I only need last 3000 elements only to proceed further.

for that I have tried following solution.

//skipping first 2000 elements
list = list.Skip(5000 - 3000).ToArray();

This solution is actually giving me desired solution, but when I ran profiler on my code, It is showing huge amount memory allocation on this line.

I have to use Array only due to carried on legacy. and very frequent ToArray() doesn't seem to be good for performance.

there is also possible solution,

//reversing whole list
Array.Reverse(list);
//restricting size of an array to 3000,
//so first (as reversed the list, they are last 3000 elements) 
Array.Resize(ref list, 3000);
//again reversing list to make it proper order
Array.Reverse(list);

but this is even worse in time complexity.

Is there any better solution for this, which doesn't need casting from List to Array ?

Amit
  • 1,821
  • 1
  • 17
  • 30
  • 1
    Do you *have* to have those elements in an array rather than just as an `IEnumerable`? Does `ArraySegment` help? It's hard to help when we don't know what you're trying to do with the rest... – Jon Skeet Jul 05 '17 at 14:10
  • What is `list`? – Tim Schmelter Jul 05 '17 at 14:10
  • @JonSkeet Yes sir, I know I should have them on `IEnumerable` but decision to make this change is not in my hand. So I have to have it in Array only! And I don't have any specific requirement with resultant array. I'll iterate through it to read the elements. – Amit Jul 05 '17 at 14:11
  • @TimSchmelter It is Array of integer. – Amit Jul 05 '17 at 14:12
  • If you are comfortable with `unsafe` code, you could use [one of these](https://stackoverflow.com/questions/5099604/any-faster-way-of-copying-arrays-in-c) methods, though his benchmarking doesn't show much difference to `Array.Copy` as far as performance goes. – Bradley Uffner Jul 05 '17 at 14:15

3 Answers3

6

If you absolutely have to use an array, then Array.Copy is probably your friend:

int[] smallerArray = new int[array.Length - 2000];
Array.Copy(array, 2000, smallerArray, 0, smallerArray.Length);

I'd expect that to be a bit more efficient than using Take followed by ToArray.

Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
1

If list is a List<> you can use List.GetRange:

int lastN = 3000;
var sublist = list.GetRange(list.Count - lastN, lastN);
var array = sublist.ToArray();

This is more efficient because List.ToArray uses Array.Copy.


If list is an int[] as commented it's even more efficient:

int lastN = 3000;
int[] result = new int[lastN];
Array.Copy(list, list.Length - lastN, result, 0, lastN); 
Tim Schmelter
  • 450,073
  • 74
  • 686
  • 939
-4

you can use Skip(Provide number which you want to exclude).ToArray();

  • It is mentioned in question. I have tried this before. yes it works but I m asking for better solution. – Amit Jul 05 '17 at 14:20