Crop the first element of an array of strings without copying all elements into a new array

advertisements

Have a string array

string[] lines

I would like to remove the first element. So if the array has 5 elements, I want to end up with 4.

There is a number of ways to achieve this:

  1. Create a new string array, with the same size as the original minus one. Then simply copy all elements (except the first one). I don't like this because, well, you have to make whole new array and seemingly duplicate the memory usage (?)

  2. Use a collection like List that implements methods for this. But then it would be the same story: I would have to convert my string array to a list, then remove the first element, then convert the list to a string array (because I need a string array, not a list).

  3. System.Array.Resize() seems to be capable of "cropping" arrays, which is precisely what I need. However, it crops the "rightmost" elements, whereas I need to crop the first (leftmost) element instead.


My question is: is there a simpler way to eliminate the first element in a string array, ending up with an array whose size is one less than the original's?


I don't know what you want to use the "cropped" version for, but a very cheap thing to do is top wrap lines in an ArraySegment<>, like this:

  var cropped = new ArraySegment<string>(lines, 1, 4);

Since .NET 4.5 (from 2012), ArraySegment<> implements some interfaces, so you can do things like:

  foreach (var l in cropped)
  {
      // ...
  }

(uses an explicit interface implementation on ArraySegment<>, the iteration variable l is strongly typed).

Remember that this is just a wrapper around the original array instance. If that array is modified, this is reflected in the ArraySegment<>. There was no copying (not even a shallow one).


If you need indexing and so on, box the value of your ArraySegment<> struct to either IReadOnlyList<> or IList<>:

  IReadOnlyList<string> croppedB = new ArraySegment<string>(lines, 1, 4);

or:

  IList<string> croppedC = new ArraySegment<string>(lines, 1, 4);