Як додати новий елемент у існуючий масив рядків у C # .net?
Мені потрібно зберегти наявні дані.
Як додати новий елемент у існуючий масив рядків у C # .net?
Мені потрібно зберегти наявні дані.
Відповіді:
Я використовую список, якщо вам потрібен масив з динамічним розміром:
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();
Мені подобається використовувати це, оскільки це однолінійне і дуже зручно вставляти в оператор переключення, простий if-оператор або передавати як аргумент.
Редагувати:
Деяким людям це не подобається, 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це, мабуть, структура даних, яку ви хочете, а не масив для початку.
Дуже давнє запитання, але все ж хотілося додати це.
Якщо ви шукаєте однолінійку, можете скористатися наведеним нижче кодом. Він поєднує конструктор списку, який приймає численні та "новий" (з моменту виникнення питання) ініціалізатор синтаксису.
myArray = new List<string>(myArray) { "add this" }.ToArray();
Масиви в C # є незмінними , наприклад 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 для першого параметра.
Є списки, які можуть динамічно виділяти нові слоти для нових елементів. Це, наприклад, Список <T> . Вони містять незмінні масиви та змінюють їх розмір за потреби (Список <T> не є пов'язаним виконанням списку!). ArrayList - те саме, що не має Generics (з масивом Object ).
LinkedList <T> - реальна реалізація пов'язаного списку. На жаль, ви можете додати до списку лише елементи LinkListNode <T>, тож вам потрібно перетворити власні елементи списку в цей тип вузла. Я думаю, його використання є рідкістю.
Aray.Resizeможете змінити розмір масиву, не втрачаючи його вміст. docs.microsoft.com/en-us/dotnet/api/…
Ви можете розширити відповідь, надану @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;
}
Усі запропоновані відповіді виконують те саме, що вони кажуть, що хотіли б уникнути, створюючи новий масив і додаючи новий запис до нього, лише із втраченими накладними витратами. LINQ не є магічним, список T - це масив з буферним простором з деяким додатковим простором, щоб уникнути зміни розміру внутрішнього масиву при додаванні елементів.
Усі абстракції повинні вирішити одну і ту ж проблему, створити масив без порожніх слотів, який містить усі значення, і повернути їх.
Якщо вам потрібна гнучкість, ви можете створити достатньо великий список, який ви можете використовувати для передачі, то зробіть це. інше використовувати масив і поділитися цим об'єктом, безпечним для потоків. Також новий Span допомагає обмінюватися даними, не копіюючи списки навколо.
Щоб відповісти на запитання:
Array.Resize(ref myArray, myArray.Length + 1);
data[myArray.Length - 1] = Value;
Append<TSource>До IEnumerable<TSource>.NET Framework 4.7.1 та .NET Core 1.0 додано новий метод .
Ось як його використовувати:
var numbers = new [] { "one", "two", "three" };
numbers = numbers.Append("four").ToArray();
Console.WriteLine(string.Join(", ", numbers)); // one, two, three, four
Зауважте, що якщо ви хочете додати елемент на початку масиву, ви можете скористатися новим Prepend<TSource>методом.
Використання списку було б найкращим варіантом для управління пам’яттю.
Що з використанням методу розширення? Наприклад:
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);
Зауважте, це імітує таку поведінку розширення Uniq Uniq (використовується для об'єднання двох масивів у новий) та вимагає функціонування бібліотеки Linq.
Я згоден з Едом. C # не робить це просто так, як це робить VB із ReDim Preserve. Без колекції вам доведеться скопіювати масив у більший.
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();
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
Оскільки це питання не задоволено наданою відповіддю, я хотів би додати цю відповідь :)
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;
}
}
}
}