LJM
LJM

Reputation: 6444

Subset of Array in C#

If I have an array with 12 elements and I want a new array with that drops the first and 12th elements. For example, if my array looks like this:

__ __ __ __ __ __ __ __ __ __ __ __
a  b  c  d  e  f  g  h  i  j  k  l
__ __ __ __ __ __ __ __ __ __ __ __

I want to either transform it or create a new array that looks like

__ __ __ __ __ __ __ __ __ __

b  c  d  e  f  g  h  i  j  k 
__ __ __ __ __ __ __ __ __ __

I know I can do it by iterating over them. I was just wondering if there was a cleaner way built into C#.

Upvotes: 74

Views: 100390

Answers (10)

DarkDuck
DarkDuck

Reputation: 343

LINQ has proved to be extremely slow regarding demanding operations in my tests. Array.Copy as shown in the accepted answer is much faster. however, the fastest method so far to achieve your goal is by doing this:

var sub = input[startIndex..endIndex];

(note that there are two dots between the start and end index)

I don't know why no one talks about this feature, please tell me if there is something wrong with this method.

Upvotes: 0

Dmytro Ovdiienko
Dmytro Ovdiienko

Reputation: 1116

Using the ReadOnlySpan struct the code of the substr for array may look like following:

var subArray = input.AsSpan(offset, length).ToArray();

Upvotes: 0

Prasanth Louis
Prasanth Louis

Reputation: 5056

C# 8 has a Range and Index type

char[] a = { 'a', 'b', 'c',  'd',  'e',  'f',  'g',  'h',  'i',  'j',  'k',  'l' };
Index i1 = 1;  // number 1 from beginning
Index i2 = ^1; // number 1 from end
var slice = a[i1..i2]; // { 'b','c','d','e','f','g','h','i','j' }

Upvotes: 32

Noldorin
Noldorin

Reputation: 147340

LINQ is your friend. :)

var newArray = oldArray.Skip(1).Take(oldArray.Length - 2).ToArray();

Somewhat less efficient than manually creating the array and iterating over it of course, but far simple...

The slightly lengithier method that uses Array.Copy is the following.

var newArray = new int[oldArray.Count - 2];
Array.Copy(oldArray, 1, newArray, 0, newArray.Length);

Upvotes: 118

orad
orad

Reputation: 16066

You can use ArraySegment<T> structure like below:

var arr = new[] { 1, 2, 3, 4, 5 };
var offset = 1;
var count = 2;
var subset = new ArraySegment<int>(arr, offset, count)
             .ToArray(); // output: { 2, 3 }

Check here for an extension method that makes use of it even easier.

Upvotes: 10

Tobias
Tobias

Reputation: 5108

If you want to avoid manually indexing the array. Don't try to pull request that anywhere though:

var newArray = oldArray.Skip(1).Reverse().Skip(1).Reverse().ToArray()

Upvotes: 0

Dr. Wily&#39;s Apprentice
Dr. Wily&#39;s Apprentice

Reputation: 10280

Linq is all nice and snazzy, but if you're looking for a 1-liner you could just throw together your own utility functions:

static class ArrayUtilities
{
    // create a subset from a range of indices
    public static T[] RangeSubset<T>(this T[] array, int startIndex, int length)
    {
        T[] subset = new T[length];
        Array.Copy(array, startIndex, subset, 0, length);
        return subset;
    }

    // create a subset from a specific list of indices
    public static T[] Subset<T>(this T[] array, params int[] indices)
    {
        T[] subset = new T[indices.Length];
        for (int i = 0; i < indices.Length; i++)
        {
            subset[i] = array[indices[i]];
        }
        return subset;
    }
}

So then you could do the following:

        char[] original = new char[] { 'a', 'b', 'c', 'd', 'e', 'f', 'g' };

        // array containing 'b' - 'f'
        char[] rangeSubset = original.RangeSubset(1, original.Length - 2);

        // array containing 'c', 'd', and 'f'
        char[] specificSubset = original.Subset(2, 3, 5);

Upvotes: 40

Bob
Bob

Reputation: 99734

You can do this with Array.Copy or LINQ.

var letters = string[] { "a", "b", "c", "d", "e", "f", "g", "h", "i" };

int length = letters.Length - 2;
var items = new string[length];
Array.Copy(letters, 1, items, 0, length);
// or
var items = letters.Skip(1).Take(length).ToArray();

Upvotes: 6

Dan Bystr&#246;m
Dan Bystr&#246;m

Reputation: 9244

Array.Copy() will do that for you, but you still have to create your new array with its correct size.

Upvotes: 3

string[] s = initialize the array...

var subset = s.Skip(1).Take(s.Length - 2).ToArray();

Upvotes: 1

Related Questions