Как добавить новый элемент в существующий строковый массив в С#.net?
Мне нужно сохранить существующие данные.
Как добавить новый элемент в существующий строковый массив в С#.net?
Мне нужно сохранить существующие данные.
Я бы использовал List, если вам нужен массив с динамическим размером:
List<string> ls = new List<string>();
ls.Add("Hello");
Это может быть решение;
Array.Resize(ref array, newsize);
array[newsize - 1] = "newvalue"
Но для массива с динамическим размером я бы тоже предпочел список.
Использование LINQ:
arr = (arr ?? Enumerable.Empty<string>()).Concat(new[] { newitem }).ToArray();
Мне нравится использовать это, поскольку это однострочный и очень удобно вставлять в оператор switch, простой оператор if или передавать как аргумент.
EDIT:
Некоторым людям не нравится new[] { newitem }
, потому что он создает небольшой временный массив с одним элементом. Вот версия, использующая Enumerable.Repeat
, которая не требует создания какого-либо объекта (по крайней мере, не на поверхности). Итераторы .NET, вероятно, создают кучу объектов конечного автомата в таблице).
arr = (arr ?? Enumerable.Empty<string>()).Concat(Enumerable.Repeat(newitem,1)).ToArray();
И если вы уверены, что массив никогда не будет null
для начала, вы можете упростить его:
arr.Concat(Enumerable.Repeat(newitem,1)).ToArray();
Обратите внимание, что если вы хотите добавить элементы в упорядоченную коллекцию, List
, вероятно, вам нужна структура данных, а не массив.
Массивы в С# являются неизменяемыми, например string[]
, int[]
. Это означает, что вы не можете изменить их размер. Вам нужно создать новый массив.
Вот код для Array.Resize:
public static void Resize<T>(ref T[] array, int newSize)
{
if (newSize < 0)
{
throw new ArgumentOutOfRangeException("newSize", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
}
T[] sourceArray = array;
if (sourceArray == null)
{
array = new T[newSize];
}
else if (sourceArray.Length != newSize)
{
T[] destinationArray = new T[newSize];
Copy(sourceArray, 0, destinationArray, 0, (sourceArray.Length > newSize) ? newSize : sourceArray.Length);
array = destinationArray;
}
}
Как вы можете видеть, он создает новый массив с новым размером, копирует содержимое исходного массива и устанавливает ссылку на новый массив. Подсказка для этого - ключевое слово ref для первого параметра.
Существуют списки, которые могут динамически распределять новые слоты для новых элементов. Это, например, Список & л; Т>. Они содержат неизменяемые массивы и изменяют их размер при необходимости (List & lt; T> не является реализацией связанного списка!). ArrayList - это то же самое без Generics (с массивом Object).
LinkedList & lt; T> - это реальная реализация связанного списка. К сожалению, вы можете добавить в список только элементы LinkListNode & lt; T>, поэтому вы должны обернуть свои собственные элементы списка в этот тип узла. Я думаю, что его использование редко.
Array.Resize(ref youur_array_name, your_array_name.Length + 1);
your_array_name[your_array_name.Length - 1] = "new item";
Очень старый вопрос, но все же хотел добавить это.
Если вы ищете один лайнер, вы можете использовать приведенный ниже код. Он объединяет конструктор списка, который принимает перечислимый и "новый" (с учетом вопроса) синтаксис инициализатора.
myArray = new List<string>(myArray) { "add this" }.ToArray();
Вы можете расширить ответ, предоставленный @Stephen Chung, используя его логику на основе LINQ для создания метода расширения с использованием общего типа.
public static class CollectionHelper
{
public static IEnumerable<T> Add<T>(this IEnumerable<T> sequence, T item)
{
return (sequence ?? Enumerable.Empty<T>()).Concat(new[] { item });
}
public static T[] AddRangeToArray<T>(this T[] sequence, T[] items)
{
return (sequence ?? Enumerable.Empty<T>()).Concat(items).ToArray();
}
public static T[] AddToArray<T>(this T[] sequence, T item)
{
return Add(sequence, item).ToArray();
}
}
Затем вы можете вызвать его непосредственно в массиве, подобном этому.
public void AddToArray(string[] options)
{
// Add one item
options = options.AddToArray("New Item");
// Add a
options = options.AddRangeToArray(new string[] { "one", "two", "three" });
// Do stuff...
}
По общему признанию, метод AddRangeToArray() кажется немного избыточным, поскольку у вас есть те же функции с Concat(), но таким образом конечный код может "работать" с массивом напрямую в отличие от этого:
options = options.Concat(new string[] { "one", "two", "three" }).ToArray();
Если вы по какой-то причине много работаете с массивами и не списками, этот общий типизированный метод возврата Add
может помочь
public static T[] Add<T>(T[] array, T item)
{
T[] returnarray = new T[array.Length + 1];
for (int i = 0; i < array.Length; i++)
{
returnarray[i] = array[i];
}
returnarray[array.Length] = item;
return returnarray;
}
вы можете моделировать Add
на Extension Method
и IEnumerable.Concat()
public static class ArrayExtensions
{
public static string[] Add(this string[] array, string item)
{
return array.Concat(new[] {item}).ToArray();
}
}
Все предлагаемые ответы делают то же самое, что, как они говорят, они хотели бы избежать, создавая новый массив и добавляя в него новую запись только с потерянными дополнительными затратами. LINQ не волшебство, список T - это массив с буферным пространством с некоторым дополнительным пространством, чтобы избежать изменения размера внутреннего массива при добавлении элементов.
Все абстракции должны решить одну и ту же проблему, создать массив без пустых слотов, который содержит все значения и возвращает их.
Если вам нужна гибкость, вы можете создать достаточно большой список, который вы можете использовать для передачи, тогда сделайте это. иначе используйте массив и поделитесь этим потокобезопасным объектом. Кроме того, новый Span помогает обмениваться данными без необходимости копировать списки.
Чтобы ответить на вопрос:
Array.Resize(ref myArray, myArray.Length + 1);
data[myArray.Length - 1] = Value;
Использование списка будет вашим лучшим вариантом для управления памятью.
Я согласен с Эд. С# не делает так легко, как VB делает с ReDim Preserve. Без коллекции вам придется скопировать массив в более крупный.
string str = "string ";
List<string> li_str = new List<string>();
for (int k = 0; k < 100; i++ )
li_str.Add(str+k.ToString());
string[] arr_str = li_str.ToArray();
Как насчет использования метода расширения? Например:
public static IEnumerable<TSource> Union<TSource>(this IEnumerable<TSource> source, TSource item)
{
return source.Union(new TSource[] { item });
}
например:
string[] sourceArray = new []
{
"foo",
"bar"
}
string additionalItem = "foobar";
string result = sourceArray.Union(additionalItem);
Обратите внимание, что это имитирует это расширение Linq Uniion (используется для объединения двух массивов в новое) и требует, чтобы библиотека Linq функционировала.
private static string[] GetMergedArray(string[] originalArray, string[] newArray)
{
int startIndexForNewArray = originalArray.Length;
Array.Resize<string>(ref originalArray, originalArray.Length + newArray.Length);
newArray.CopyTo(originalArray, startIndexForNewArray);
return originalArray;
}
Почему бы не попробовать использовать класс Stringbuilder. Он имеет такие методы, как .insert и .append. Подробнее об этом можно прочитать здесь: http://msdn.microsoft.com/en-us/library/2839d5h5(v=vs.71).aspx
К сожалению, использование списка не будет работать во всех ситуациях. Список и массив фактически различны и не являются взаимозаменяемыми на 100%. Это будет зависеть от обстоятельств, если это будет приемлемой работой.
Поскольку этот вопрос не удовлетворен предоставленным ответом, я хотел бы добавить этот ответ:)
public class CustomArrayList<T>
{
private T[] arr; private int count;
public int Count
{
get
{
return this.count;
}
}
private const int INITIAL_CAPACITY = 4;
public CustomArrayList(int capacity = INITIAL_CAPACITY)
{
this.arr = new T[capacity]; this.count = 0;
}
public void Add(T item)
{
GrowIfArrIsFull();
this.arr[this.count] = item; this.count++;
}
public void Insert(int index, T item)
{
if (index > this.count || index < 0)
{
throw new IndexOutOfRangeException( "Invalid index: " + index);
}
GrowIfArrIsFull();
Array.Copy(this.arr, index, this.arr, index + 1, this.count - index);
this.arr[index] = item; this.count++; }
private void GrowIfArrIsFull()
{
if (this.count + 1 > this.arr.Length)
{
T[] extendedArr = new T[this.arr.Length * 2];
Array.Copy(this.arr, extendedArr, this.count);
this.arr = extendedArr;
}
}
}
}
Так что, если у вас есть существующий массив, мое быстрое исправление будет
var tempList = originalArray.ToList();
tempList.Add(newitem);
Теперь просто замените исходный массив новым
originalArray = tempList.ToArray();