У меня есть «проект», в котором мне разрешено использовать только массивы. В этом проекте мне нужно прочитать данные из txt-файла, а затем, например, найти второе лучшее время круга среди бегунов и т. д.
Я всегда могу рассчитать правильный ответ, но я не уверен в своем управлении массивом.
Как вы знаете, в C# вы должны указать длину массива при инициализации. Поскольку есть задачи, в которых я не знаю размер массива, я объявил гораздо больший массив, а затем использовал эту функцию:
private static string[] ArraySimplyfier(string[] strs, int index)
{
string[] returnStr = new string[index];
for (int i = 0; i < returnStr.Length; i++)
{
returnStr[i] = strs[i];
}
return returnStr;
}
Как вы можете видеть, он «очищает» нули из массива, но дело в том, что я должен создать его для каждого типа массива, что не идеально. У вас есть другие идеи для моей проблемы?
Вы можете использовать IEnumerable<>?
Я думаю, что это и было целью этого проекта: показать вам, что массивы имеют фиксированный размер. Если вы хотите динамично расти, используйте вместо этого List<T>.
Что значит «Я должен создать его для каждого типа массива, который не идеален». иметь в виду? Ваш код работает, и если вам нужно выполнить упражнение, показывающее, как работают массивы, вы его выполнили.
Итак, вот пример из моего проекта: в базе данных много автомобилей, и, например, мне нужно собрать все автомобили красного цвета в массив. Я не узнаю, насколько велик массив, пока не соберу все элементы. И да, это работает, мне просто было любопытно, может быть, кто-то знает лучший способ
поэтому вы либо используете динамически растущий тип коллекции, такой как список, либо живете с ним. Другого пути нет, пока вы используете массив.
«но дело в том, что я должен создать его для каждого типа массива, который не идеален». Что вы подразумеваете под «для каждого типа»? К каким типам вы относитесь? Каковы возможные типы для вашего массива?
Ваш подход прекрасен, если вы определяете поведение при превышении буфера массива. Кроме того, вам, вероятно, следует использовать Array.Copy или CopyTo вместо цикла for, если это разрешено.





Вы можете использовать дженерики. Таким образом, у вас есть один метод для каждого типа массива.
Ваш метод будет выглядеть так:
private static T[] ArraySimplyfier<T>(T[] array, int index)
{
T[] result = new T[index];
for (int i = 0; i < result.Length; i++)
{
result[i] = array[i];
}
return result;
}
и вы можете вызвать этот метод следующим образом:
//example for a string array
ArraySimplyfier<string>(new string[45], 17); //replace 'new string[45]' with your array
как дженерики решат проблему неизвестного размера массива?
Это позволяет мне вызывать ArraySimplifier для любых массивов.
Он сказал: «Как вы видите, это «очищает» нули из массива, но дело в том, что я должен создать его для каждого типа массива, что не идеально. У вас есть какие-либо другие идеи для моей проблемы?» Так что для меня это звучит так, как будто его решение работает, но ему нужно будет написать один и тот же метод для каждого возможного типа данных. С дженериками в этом больше нет необходимости.
Действительно, вы, кажется, единственный, кто фокусируется на этом вопросе.
Да, все предложенные методы были хороши и работали, но я выберу решение @Tomsen!
Создание новых, больших массивов и копирование - это путь. Вы на правильном пути. Это в основном то, что List делает под капотом (оптимизированным способом).
Если вам это нужно для нескольких типов, вы можете изучить общие методы. Обобщения позволяют указывать классы и методы для нескольких типов.
Итак, ваш вопрос звучит так: «Как мне заранее узнать количество элементов при фильтрации массива, чтобы получить размер целевого массива?» - нет.
Либо дважды выполните цикл по исходному массиву, один раз, чтобы получить количество, а затем сделайте копию, либо начните с массива одинакового размера, сохраните количество и обрежьте массив, скопировав его в новый с размером, ограниченным числом результатов.
Список удвоится в размере, когда станет слишком маленьким, вы можете сделать то же самое. Проверьте реализацию «Add/EnsureCapacity» для списка на github.
// Adds the given object to the end of this list. The size of the list is
// increased by one. If required, the capacity of the list is doubled
// before adding the new element.
//
public void Add(T item) {
if (_size == _items.Length) EnsureCapacity(_size + 1);
_items[_size++] = item;
_version++;
}
// Ensures that the capacity of this list is at least the given minimum
// value. If the currect capacity of the list is less than min, the
// capacity is increased to twice the current capacity or to min,
// whichever is larger.
private void EnsureCapacity(int min) {
if (_items.Length < min) {
int newCapacity = _items.Length == 0? _defaultCapacity : _items.Length * 2;
// Allow the list to grow to maximum possible capacity (~2G elements) before encountering overflow.
// Note that this check works even when _items.Length overflowed thanks to the (uint) cast
if ((uint)newCapacity > Array.MaxArrayLength) newCapacity = Array.MaxArrayLength;
if (newCapacity < min) newCapacity = min;
Capacity = newCapacity;
}
}
Я почти уверен, что вы можете рассчитать необходимую длину перед инициализацией первого массива. Если это случайно (например, пользовательский ввод), вам не следует использовать массивы. Покажите нам исходную проблему, чтобы мы могли помочь.