Вопрос о массиве C # (split) - PullRequest
2 голосов
/ 25 июля 2010

Вопрос очень простой - скажем, я получил функцию, которая получает массив в качестве аргументов

void calc(double[] data)

как "разбить" эти данные на два подмассива и передать таким подфункциям, как эта

calc_sub(data(0, length/2));
cals_sub(data(length /2, length /2));

Надеюсь, у вас есть идея - на c ++ я написал бы это

void calc(double * data, int len)
{
   calc_sub(data, len / 2); //this one modifies data!!
   calc_sub(data + len / 2, len / 2); //this one modifies data too!!
}

Как сделать то же самое в C # без ненужного копирования памяти?Мне нужно 2 копии памяти здесь.1) из данных в разделенные данные 2) calc_sub 3) из разделенных данных обратно в данные!Это огромная трата времени и памяти!

Ответы [ 5 ]

8 голосов
/ 25 июля 2010

Возможно, проще всего использовать LINQ Взять и Пропустить методы расширения:

int half = data.Length / 2;
double[] sub1 = data.Take(half).ToArray();
double[] sub2 = data.Skip(half).ToArray();
5 голосов
/ 25 июля 2010

Короткий ответ: чтобы получить подмассив, вам нужно было бы создать новый массив и скопировать элементы ... Или, если бы вы использовали c ++, вы бы запоминали.

Теперь, почему бы просто не использовать подход смещения / подсчета? При вызове calc_sub(blargh[] array) вместо этого используйте calc_sub(blargh[] array, int offset, int count)?

Это в основном способ передачи c # указателя на элемент start / half-pos и указание функции работать только с половиной элементов массива.


Я должен отметить, что если вы не работаете с огромными двойными массивами, вам не стоит об этом беспокоиться. 64 бита = 8 байт. Даже если у вас есть массив из 1000 элементов, это 8000 байт, ~ 8 КБ памяти, которые вы в значительной степени освободите менее чем за секунду ...

Теперь, это всегда хорошая идея, чтобы сохранить память там, где это возможно, но я бы посчитал это преждевременной оптимизацией.

Следует также отметить, что массивы передаются по ссылке, поскольку они действительно являются объектами, а не целыми числами или строками, поэтому этот метод лучше всего подходит для памяти [он не копирует массив; он дает что-то вроде указателя на объект массива], но он ограничен в том, что изменение массива в вашей функции изменит массив, переданный за пределы вызова вашей функции.

2 голосов
/ 25 июля 2010

В зависимости от того, что делает calc_sub, вы можете создать класс IEnumerable, который принимает массив и выполняет итерацию по некоторой части массива. Что-то вроде ArraySegment , но лучше .

1 голос
/ 25 июля 2010

Если вы можете заставить метод calc_sub принимать IEnumerable<double> вместо double[], вы можете использовать методы расширения для создания выражений, которые возвращают часть массива:

void calc(double[] data) {
  int half = data.Length / 2;
  calc_sub(data.Take((half));
  calc_sub(data.Skip(half));
}

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

1 голос
/ 25 июля 2010

Продолжайте и напишите свою собственную функцию подмассива следующим образом:

public static class ArrayExtensions
{
  T[] SubArray<T>(this T[] arr, int startIndex,int count)
  {
    var sub = new T[count];
    Array.Copy(arr,startIndex,sub,o,count);
    return sub;
  }
}

и затем вы можете использовать его как:

void calc(double[] data)
{
  var half = data.Length /2;
  data.SubArray(0, half ));
  data.SubArray(half , half ));
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...