2009-11-24 6 views
31

Если у меня есть массив из 12 элементов, и я хочу, чтобы новый массив сбрасывал первый и 12-й элементы. Например, если мой массив выглядит следующим образом:Подмножество массива в C#

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

Я хочу либо преобразовать его или создать новый массив, который выглядит как

__ __ __ __ __ __ __ __ __ __ 

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

Я знаю, что могу сделать это итерация над ними. Мне просто интересно, есть ли более чистый способ, встроенный в C#.

** ОБНОВЛЕНО ДЛЯ ИСПЫТАНИЯ ТИПО. Изменено 10 элементов на 12 элементов.

+0

Не является ли «j» 10-м элементом массива? Или вы имели в виду первый и последний элементы? –

ответ

66

LINQ - ваш друг. :)

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

Несколько менее эффективен, чем вручную создавать массив и итерацию над ним, конечно, но далеко не просто ...

Слегка lengithier метод, который использует Array.Copy является следующее.

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

Мне очень понравился ваш оригинальный ответ. LINQ был моим другом на некоторое время. Я просто никогда не использовал пропустить и взять. Благодарю. – LJM

+0

@L. Мозер: Нет проблем - тоже изменился. :) И да, я думаю, что каждую неделю или около того я обнаруживаю новый полезный метод LINQ. – Noldorin

+3

Хотя Linq удобен, он намного менее эффективен – Mario

5

Вы можете сделать это с помощью Array.Copy или 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(); 
1
string[] s = initialize the array... 

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

интересное решение – JohnIdol

2

Array.Copy() сделает это за вас, но вам все равно придется создать новый массив с его правильным размером.

30

Linq это все красиво и эффектный, но если вы ищете 1-лайнер можно просто выбросить вместе ваши собственные функции полезности:

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; 
    } 
} 

Итак вы могли бы сделать следующее:

 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); 
+2

Мне очень нравится это решение. –

0

Если вы хотите избежать ручного индексации массива. Не пытайтесь вытащить запрос, в любом месте, хотя:

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

Кажется, что это не последний элемент. –

+0

спасибо @NathanTuggy, забыли об этом. – Tobias

2

Вы можете использовать ArraySegment<T> структуру, как показано ниже:

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 } 

Проверьте здесь для extension method, что делает использование еще проще.

Смежные вопросы