Jak dodać nowy element do istniejącej tablicy ciągów w C # .net?
Muszę zachować istniejące dane.
Jak dodać nowy element do istniejącej tablicy ciągów w C # .net?
Muszę zachować istniejące dane.
Odpowiedzi:
Użyłbym listy, jeśli potrzebujesz tablicy o dynamicznym rozmiarze:
List<string> ls = new List<string>();
ls.Add("Hello");
To mogłoby być rozwiązanie;
Array.Resize(ref array, newsize);
array[newsize - 1] = "newvalue"
Ale dla tablicy o dynamicznym rozmiarze wolałbym też listę.
Korzystanie z LINQ:
arr = (arr ?? Enumerable.Empty<string>()).Concat(new[] { newitem }).ToArray();
Lubię tego używać, ponieważ jest to jednolinijkowe i bardzo wygodne do osadzenia w instrukcji switch, prostej instrukcji if lub przekazaniu jako argumentu.
EDYTOWAĆ:
Niektórzy ludzie nie lubią, new[] { newitem }ponieważ tworzy małą, jednopozycyjną, tymczasową tablicę. Oto wersja używająca Enumerable.Repeat, która nie wymaga tworzenia żadnego obiektu (przynajmniej nie na powierzchni - iteratory .NET prawdopodobnie tworzą kilka obiektów automatu stanowego pod tabelą).
arr = (arr ?? Enumerable.Empty<string>()).Concat(Enumerable.Repeat(newitem,1)).ToArray();
A jeśli masz pewność, że tablica nigdy nullsię nie zaczyna, możesz ją uprościć, aby:
arr.Concat(Enumerable.Repeat(newitem,1)).ToArray();
Zauważ, że jeśli chcesz dodać elementy do uporządkowanej kolekcji, Listprawdopodobnie jest to pożądana struktura danych, a nie tablica, od której należy zacząć.
Bardzo stare pytanie, ale nadal chciałem to dodać.
Jeśli szukasz jednej linijki, możesz użyć poniższego kodu. Łączy konstruktor listy, który akceptuje wyliczalną i "nową" (od czasu postawienia pytania) składnię inicjalizatora.
myArray = new List<string>(myArray) { "add this" }.ToArray();
Tablice w C # są niezmienne , np string[],int[] . Oznacza to, że nie możesz zmienić ich rozmiaru. Musisz stworzyć zupełnie nową tablicę.
Oto kod dla 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;
}
}
Jak widać, tworzy nową tablicę z nowym rozmiarem, kopiuje zawartość tablicy źródłowej i ustawia odwołanie do nowej tablicy. Wskazówka do tego jest ref słowo kluczowe dla pierwszego parametru.
Istnieją listy, które mogą dynamicznie przydzielać nowe miejsca na nowe przedmioty. To jest np. List <T> . Zawierają one niezmienne tablice i zmieniają ich rozmiar w razie potrzeby (List <T> nie jest połączoną implementacją listy!). ArrayList to to samo bez typów generycznych (z tablicą Object ).
LinkedList <T> to prawdziwa implementacja listy połączonej. Niestety możesz dodać tylko elementy LinkListNode <T> do listy, więc musisz zawinąć własne elementy listy w ten typ węzła. Myślę, że jego użycie jest rzadkie.
Aray.Resizemożna zmienić rozmiar tablicy bez utraty jej zawartości. docs.microsoft.com/en-us/dotnet/api/ ...
Możesz rozwinąć odpowiedź udzieloną przez @Stephen Chung, używając jego logiki opartej na LINQ, aby utworzyć metodę rozszerzenia przy użyciu typu ogólnego.
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();
}
}
Następnie możesz wywołać go bezpośrednio w tablicy w ten sposób.
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...
}
Trzeba przyznać, że metoda AddRangeToArray () wydaje się nieco przesadzona, ponieważ masz tę samą funkcjonalność z Concat (), ale w ten sposób kod końcowy może „działać” bezpośrednio z tablicą, w przeciwieństwie do tego:
options = options.Concat(new string[] { "one", "two", "three" }).ToArray();
Więc jeśli masz istniejącą tablicę, moją szybką poprawką będzie
var tempList = originalArray.ToList();
tempList.Add(newitem);
Teraz po prostu zastąp oryginalną tablicę nową
originalArray = tempList.ToArray();
jeśli z jakiegoś powodu dużo pracujesz z tablicami, a nie z listami, ta ogólna metoda zwracania typowego powrotu Addmoże pomóc
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;
}
Dodano nową Append<TSource>metodęIEnumerable<TSource> od .NET Framework 4.7.1 i .NET Core 1.0.
Oto jak z niego korzystać:
var numbers = new [] { "one", "two", "three" };
numbers = numbers.Append("four").ToArray();
Console.WriteLine(string.Join(", ", numbers)); // one, two, three, four
Zauważ, że jeśli chcesz dodać element na początku tablicy, możesz Prepend<TSource>zamiast tego użyć nowej metody.
Wszystkie proponowane odpowiedzi działają tak samo, jak to, czego chcieliby uniknąć, tworząc nową tablicę i dodając do niej nowy wpis tylko z większą stratą narzutu. LINQ nie jest magią, lista T to tablica z obszarem buforu z dodatkową przestrzenią, aby uniknąć zmiany rozmiaru tablicy wewnętrznej po dodaniu elementów.
Wszystkie abstrakcje muszą rozwiązać ten sam problem, utworzyć tablicę bez pustych gniazd, które przechowują wszystkie wartości i zwrócić je.
Jeśli potrzebujesz elastyczności i możesz utworzyć wystarczająco dużą listę, której możesz użyć, aby ją przekazać, zrób to. w przeciwnym razie użyj tablicy i udostępnij ten bezpieczny wątkowo obiekt. Ponadto nowy Span pomaga udostępniać dane bez konieczności kopiowania list.
Aby odpowiedzieć na pytanie:
Array.Resize(ref myArray, myArray.Length + 1);
data[myArray.Length - 1] = Value;
A co z użyciem metody rozszerzenia? Na przykład:
public static IEnumerable<TSource> Union<TSource>(this IEnumerable<TSource> source, TSource item)
{
return source.Union(new TSource[] { item });
}
na przykład:
string[] sourceArray = new []
{
"foo",
"bar"
}
string additionalItem = "foobar";
string result = sourceArray.Union(additionalItem);
Zauważ, że naśladuje to zachowanie rozszerzenia Uniion Linq (używanego do łączenia dwóch tablic w nową) i wymaga do działania biblioteki Linq.
Zgadzam się z Edem. C # nie czyni tego tak prostym, jak robi to VB z ReDim Preserve. Bez kolekcji musisz skopiować tablicę do większej.
ReDim Preservepo prostu kopiuje tablicę do większej. Nie ma cudownej zmiany rozmiaru tablicy.
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;
}
Wypróbuj klasę Stringbuilder . Ma metody takie jak .insert i .append. Możesz przeczytać więcej na ten temat tutaj: http://msdn.microsoft.com/en-us/library/2839d5h5(v=vs.71).aspx
Ponieważ to pytanie nie jest zadowalające z udzielonej odpowiedzi, chciałbym dodać tę odpowiedź :)
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;
}
}
}
}