Получение подмассива от существующего массива

private String[] StringSpliter(String OriginalString) {
    String newString = "";
    for (String s: OriginalString.split("(?<=\\G.{"nth position"})")) { 
        if(s.length()<3)
            newString += s +"/";
        else
            newString += StringSpliter(s) ;
    }
    return newString.split("/");
}
314
задан MikeTheLiar 30 October 2015 в 11:55
поделиться

15 ответов

Вы можете добавить его как метод расширения:

public static T[] SubArray<T>(this T[] data, int index, int length)
{
    T[] result = new T[length];
    Array.Copy(data, index, result, 0, length);
    return result;
}
static void Main()
{
    int[] data = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
    int[] sub = data.SubArray(3, 4); // contains {3,4,5,6}
}

Обновить повторное клонирование (что не было очевидным в исходном вопросе). Если вам действительно нужен глубокий клон; что-то вроде:

public static T[] SubArrayDeepClone<T>(this T[] data, int index, int length)
{
    T[] arrCopy = new T[length];
    Array.Copy(data, index, arrCopy, 0, length);
    using (MemoryStream ms = new MemoryStream())
    {
        var bf = new BinaryFormatter();
        bf.Serialize(ms, arrCopy);
        ms.Position = 0;
        return (T[])bf.Deserialize(ms);
    }
}

Это действительно требует, чтобы объекты были сериализуемыми ( [Serializable] или ISerializable ). Вы можете легко заменить любой другой сериализатор при необходимости - XmlSerializer , DataContractSerializer , protobuf-net и т. Д.

Обратите внимание, что глубокое клонирование сложно без сериализации; в частности, ICloneable в большинстве случаев трудно доверять.

440
ответ дан 23 November 2019 в 01:06
поделиться

Я думаю, что код, который вы ищете:

Array.Copy (oldArray, 0, newArray, BeginIndex, EndIndex - BeginIndex)

4
ответ дан 23 November 2019 в 01:06
поделиться

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

public class SubArray<T> : IEnumerable<T> {

   private T[] _original;
   private int _start;

   public SubArray(T[] original, int start, int len) {
      _original = original;
      _start = start;
      Length = len;
   }

   public T this[int index] {
      get {
         if (index < 0 || index >= Length) throw new IndexOutOfRangeException();
         return _original[_start + index];
      }
   }

   public int Length { get; private set; }

   public IEnumerator<T> GetEnumerator() {
      for (int i = 0; i < Length; i++) {
        yield return _original[_start + i];
      }
   }

   IEnumerator IEnumerable.GetEnumerator() {
      return GetEnumerator();
   }

}

Использование:

int[] original = { 1, 2, 3, 4, 5 };
SubArray<int> copy = new SubArray<int>(original, 2, 2);

Console.WriteLine(copy.Length); // shows: 2
Console.WriteLine(copy[0]); // shows: 3
foreach (int i in copy) Console.WriteLine(i); // shows 3 and 4
3
ответ дан 23 November 2019 в 01:06
поделиться

Array.ConstrainedCopy будет работать.

public static void ConstrainedCopy (
    Array sourceArray,
    int sourceIndex,
    Array destinationArray,
    int destinationIndex,
    int length
)
2
ответ дан 23 November 2019 в 01:06
поделиться

Вы можете сделать это довольно легко;

    object[] foo = new object[10];
    object[] bar = new object[7];   
    Array.Copy(foo, 3, bar, 0, 7);  
8
ответ дан 23 November 2019 в 01:06
поделиться

Вы можете использовать Array.Copy (...) для копирования в новый массив после того, как вы его создали, но я не думаю, что существует метод, который создает новый массив , а копирует ряд элементов.

Если вы используете .NET 3.5, вы могли бы использовать LINQ:

302
ответ дан 23 November 2019 в 01:06
поделиться

I видите, что вы хотите делать клонирование, а не просто копировать ссылки. В этом случае вы можете использовать .Select для проецирования элементов массива в их клоны. Например, если в ваших элементах реализован IClonable , вы можете сделать что-то вроде этого:

var newArray = array.Skip(3).Take(5).Select(eachElement => eachElement.Clone()).ToArray();

Примечание. Для этого решения требуется .NET Framework 3.5.

33
ответ дан 23 November 2019 в 01:06
поделиться

Основываясь на ответе Марка, но добавляя желаемое поведение клонирования

public static T[] CloneSubArray<T>(this T[] data, int index, int length)
    where T : ICloneable
{
    T[] result = new T[length];
    for (int i = 0; i < length; i++)
    { 
        var original = data[index + i];
        if (original != null)
            result[i] = (T)original.Clone();            
    return result;
}

И если реализация ICloneable слишком похожа на тяжелую работу, то рефлексивная работа с использованием библиотеки Copyable Хаварда Страндена для выполнения требуется тяжелый подъем.

using OX.Copyable;

public static T[] DeepCopySubArray<T>(
    this T[] data, int index, int length)
{
    T[] result = new T[length];
    for (int i = 0; i < length; i++)
    { 
        var original = data[index + i];
        if (original != null)
            result[i] = (T)original.Copy();            
    return result;
}

Обратите внимание, что реализация OX.Copyable работает с любым из:

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

  • Его тип должен иметь конструктор без параметров или
  • Он должен быть Копируемым, или
  • Он должен иметь IInstanceProvider, зарегистрированный для его типа.

Таким образом, это должно охватывать практически любую вашу ситуацию. Если вы клонируете объекты, где подграф содержит такие вещи, как подключения к базе данных или файлы / потоки, у вас, очевидно, есть проблемы, но это верно для любой обобщенной глубокой копии.

8
ответ дан 23 November 2019 в 01:06
поделиться

Клонирование элементов в массиве не является чем-то универсальным. Вы хотите глубокое клонирование или простую копию всех членов?

Давайте выберем подход «наилучшего усилия»: клонирование объектов с использованием интерфейса ICloneable или двоичной сериализации:

public static class ArrayExtensions
{
  public static T[] SubArray<T>(this T[] array, int index, int length)
  {
    T[] result = new T[length];

    for (int i=index;i<length+index && i<array.Length;i++)
    {
       if (array[i] is ICloneable)
          result[i-index] = (T) ((ICloneable)array[i]).Clone();
       else
          result[i-index] = (T) CloneObject(array[i]);
    }

    return result;
  }

  private static object CloneObject(object obj)
  {
    BinaryFormatter formatter = new BinaryFormatter();

    using (MemoryStream stream = new MemoryStream())
    {
      formatter.Serialize(stream, obj);

      stream.Seek(0,SeekOrigin.Begin);

      return formatter.Deserialize(stream);
    }
  }
}

Это не идеальное решение, потому что просто существует ни один из них не будет работать для любого типа объекта.

0
ответ дан 23 November 2019 в 01:06
поделиться

Что касается клонирования, я не думаю, что сериализация вызывает ваши конструкторы. Это может нарушить инварианты классов, если вы делаете интересные вещи в ctor.

Кажется, более безопасным вариантом будет использование виртуальных методов клонирования, вызывающих конструкторы копирования.

protected MyDerivedClass(MyDerivedClass myClass) 
{
  ...
}

public override MyBaseClass Clone()
{
  return new MyDerivedClass(this);
}
0
ответ дан 23 November 2019 в 01:06
поделиться

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

Foo[] newArray = oldArray.Skip(3).Take(5).Select(item => item.Clone()).ToArray();

class Foo
{
    public Foo Clone()
    {
        return (Foo)MemberwiseClone();
    }
}
1
ответ дан 23 November 2019 в 01:06
поделиться

Рассматривали ли вы возможность использования ArraySegment ?

http://msdn.microsoft.com/en-us/library/1hsbd92d.aspx

69
ответ дан 23 November 2019 в 01:06
поделиться

Я думаю, что каждый профессиональный программист на C ++ должен иметь копию стандарта, на которую можно ссылаться. Но сесть и утомиться, прочитать от корки до корки, будет довольно ошеломляющим. В основном он написан для разработчиков (разработчиков компиляторов), и в нем почти нет объяснения причин, по которым стандарт требует определенных вещей.

Итак, я бы сказал, что для профессионального программиста на C ++ более важно иметь и читать:

  • "Язык программирования C ++" Страуструпа
  • Серия "Эффективный ..." Майера и / или серия "Исключительно ..." Саттера
  • "Внутри объектной модели C ++" Липпмана
  • "Дизайн и эволюция" Страуструпа of C ++ »

Или, по крайней мере, какое-то приличное их подмножество. Если у вас за плечами кусок этих книг, вы

1
ответ дан 23 November 2019 в 01:06
поделиться

Как насчет использования Array.ConstrainedCopy :

int[] ArrayOne = new int[8] {1,2,3,4,5,6,7,8};
int[] ArrayTwo = new int[5];
Array.ConstrainedCopy(ArrayOne, 3, ArrayTwo, 0, 7-3);

Ниже мой исходный пост. Это не сработает

Вы можете использовать Array.CopyTo :

int[] ArrayOne = new int[8] {1,2,3,4,5,6,7,8};
int[] ArrayTwo = new int[5];
ArrayOne.CopyTo(ArrayTwo,3); //starts copy at index=3 until it reaches end of
                             //either array
1
ответ дан 23 November 2019 в 01:06
поделиться

Я не уверен, насколько глубоко это действительно, но:

MyArray.Tolist (). GetRange (Partindex, Endindex) .Toarnay ()

Это немного накладной, но это может вырезать ненужный метод.

1
ответ дан 23 November 2019 в 01:06
поделиться
Другие вопросы по тегам:

Похожие вопросы: