Reputation: 6444
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
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
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
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
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
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
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
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
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
Reputation: 9244
Array.Copy() will do that for you, but you still have to create your new array with its correct size.
Upvotes: 3
Reputation: 39335
string[] s = initialize the array...
var subset = s.Skip(1).Take(s.Length - 2).ToArray();
Upvotes: 1