Fügen Sie ein neues Element in ein vorhandenes Array in c # .net ein

134

Wie füge ich ein neues Element in ein vorhandenes String-Array in C # .net ein?

Ich muss die vorhandenen Daten beibehalten.

A-Sharabiani
quelle

Antworten:

121

Ich würde eine Liste verwenden, wenn Sie ein Array mit dynamischer Größe benötigen:

List<string> ls = new List<string>();
ls.Add("Hello");
Ed S.
quelle
27
Und wenn nötig, machen Sie ls.ToArray () am Ende
Narayana
2
Die Verwendung eines anderen Mechanikers als in der Frage angegeben ist keine Antwort.
user11909
@ user2190035: Ich bin mir nicht sicher, woher du diese Idee hast, und die 111 Personen, die sich für eine Abstimmung entschieden haben, würden dir nicht zustimmen. Wenn Sie einen besseren Weg kennen, um ein Array zu erweitern, veröffentlichen Sie es auf jeden Fall. Ich bezweifle, dass Ihre Neuzuweisung und manuelle Kopie besser ist als die Verwendung einer Liste. Manchmal lautet die Antwort "Tu das nicht".
Ed S.
@ EdS.Die Frage war, wie ein Element zu einem vorhandenen String-Array hinzugefügt werden kann. Diese Antwort enthält jedoch überhaupt kein Array. Stattdessen wird eine neue Liste <> erstellt. In meiner Anwendung kann ich den Typ nicht in Liste <> ändern, daher muss ich die Größe eines Arrays ändern (eine Kopie erstellen ...). Die Antwort von Ali Ersöz hat mir geholfen.
user11909
@ user2190035: IEnumerable <T> .ToArray (). Ich schreibe jeden Tag C # und musste noch nie die Größe eines solchen Arrays ändern.
Ed S.
100

Das könnte eine Lösung sein;

Array.Resize(ref array, newsize);
array[newsize - 1] = "newvalue"

Aber für ein Array mit dynamischer Größe würde ich auch eine Liste bevorzugen.

Ali Ersöz
quelle
@Konrad, das wird sicher die Daten im Array erhalten.
Ali Ersöz
1
Dies ist nicht länger als ein paar Mal zum Aufrufen geeignet. weil die 'Resize'-Funktion eine enorme Leistung hat. Fehler für ein oder zwei Mal, das ist sehr gut.
Anzeige
53

Verwenden von LINQ:

arr = (arr ?? Enumerable.Empty<string>()).Concat(new[] { newitem }).ToArray();

Ich verwende dies gerne, da es ein Einzeiler ist und sehr praktisch ist, um es in eine switch-Anweisung, eine einfache if-Anweisung oder eine Übergabe als Argument einzubetten.

BEARBEITEN:

Einige Leute mögen es nicht, new[] { newitem }weil es ein kleines temporäres Array mit einem Element erstellt. Hier ist eine Version Enumerable.Repeat, bei der kein Objekt erstellt werden muss (zumindest nicht auf der Oberfläche - .NET-Iteratoren erstellen wahrscheinlich eine Reihe von Zustandsmaschinenobjekten unter der Tabelle).

arr = (arr ?? Enumerable.Empty<string>()).Concat(Enumerable.Repeat(newitem,1)).ToArray();

Und wenn Sie sicher sind, dass das Array niemals nullbeginnen soll, können Sie es vereinfachen, um:

arr.Concat(Enumerable.Repeat(newitem,1)).ToArray();

Beachten Sie, dass, wenn Sie einer geordneten Sammlung Elemente hinzufügen möchten, dies Listwahrscheinlich die gewünschte Datenstruktur ist und nicht zunächst ein Array.

Stephen Chung
quelle
1
Sehr schön +1. Ich habe ähnlichen Code wie eine generische Erweiterungsmethode. Ich habe den Code in diese Antwort aufgenommen: stackoverflow.com/a/11035286/673545
dblood
Dies ist sehr nützlich, wenn Sie nach "Anhängen an ein Array in einer Codezeile in c #" suchen - hoffentlich reicht dieser Kommentar aus, um es beim nächsten Mal wieder zu finden.
Gary
28

Sehr alte Frage, wollte diese aber noch hinzufügen.

Wenn Sie nach einem Einzeiler suchen, können Sie den folgenden Code verwenden. Es kombiniert den Listenkonstruktor, der eine Aufzählung akzeptiert, und die "neue" (seit der Frage aufgeworfene) Initialisierersyntax.

myArray = new List<string>(myArray) { "add this" }.ToArray();
Grimasse der Verzweiflung
quelle
26

Arrays in C # sind unveränderlich , zum Beispiel string[], int[]. Das bedeutet, dass Sie die Größe nicht ändern können. Sie müssen ein brandneues Array erstellen.

Hier ist der Code für 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;
    }
}

Wie Sie sehen, wird ein neues Array mit der neuen Größe erstellt, der Inhalt des Quellarrays kopiert und der Verweis auf das neue Array festgelegt. Der Hinweis hierfür ist das Schlüsselwort ref für den ersten Parameter.

Es gibt Listen, die neue Slots dynamisch für neue Elemente zuweisen können. Dies ist zB List <T> . Diese enthalten unveränderliche Arrays und ändern deren Größe bei Bedarf (List <T> ist keine Implementierung einer verknüpften Liste!). ArrayList ist dasselbe ohne Generics (mit Object- Array).

LinkedList <T> ist eine echte Implementierung einer verknüpften Liste. Leider können Sie der Liste nur LinkListNode <T> -Elemente hinzufügen, sodass Sie Ihre eigenen Listenelemente in diesen Knotentyp einschließen müssen. Ich denke, seine Verwendung ist ungewöhnlich.

artur02
quelle
Ich denke, Sie haben Array.Copy gemeint
user123456
2
Nur eine Antwort, die einige Informationen darüber liefert, warum dies nicht möglich ist und nicht nur die Verwendung einer Liste vorschlägt ...
Gilad Green
Ich glaube, Aray.Resizeein Array kann seine Größe ändern, ohne seinen Inhalt zu verlieren. docs.microsoft.com/en-us/dotnet/api/…
AbdelAziz AbdelLatef
24
 Array.Resize(ref youur_array_name, your_array_name.Length + 1);
 your_array_name[your_array_name.Length - 1] = "new item";
tmania
quelle
7

Sie können die Antwort von @Stephen Chung erweitern, indem Sie seine LINQ-basierte Logik verwenden, um eine Erweiterungsmethode mit einem generischen Typ zu erstellen.

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();
    }

}

Sie können es dann direkt auf dem Array aufrufen.

    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...
    }

Zugegeben, die AddRangeToArray () -Methode scheint etwas übertrieben, da Sie mit Concat () dieselbe Funktionalität haben, aber auf diese Weise kann der Endcode direkt mit dem Array "arbeiten", im Gegensatz dazu:

options = options.Concat(new string[] { "one", "two", "three" }).ToArray();
Blut
quelle
Vielen Dank. Dies war sehr hilfreich. Ich habe eine Option zum Entfernen eines Elements hinzugefügt (ich hoffe, dass dies für Sie in Ordnung ist).
Tal Segal
@ TalSegal Gern geschehen, mein Vergnügen. Verwenden Sie den Code nach Belieben!
Blut
6

Es ist besser, das Array unveränderlich und fest zu halten.

Sie können Addmit Extension Methodund simulierenIEnumerable.Concat()

public static class ArrayExtensions
    {
        public static string[] Add(this string[] array, string item)
        {
            return array.Concat(new[] {item}).ToArray();
        }
    }
Soren
quelle
5

Wenn Sie aus irgendeinem Grund viel mit Arrays und nicht mit Listen arbeiten, kann diese generische generische Rückgabemethode Addhilfreich sein

    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;
    }
stackuser83
quelle
4

Alle vorgeschlagenen Antworten machen dasselbe wie das, was sie vermeiden möchten, erstellen ein neues Array und fügen einen neuen Eintrag hinzu, nur mit mehr Overhead verloren. LINQ ist keine Zauberei. Die Liste von T ist ein Array mit einem Pufferbereich mit zusätzlichem Speicherplatz, um zu vermeiden, dass die Größe des inneren Arrays beim Hinzufügen von Elementen geändert wird.

Alle Abstraktionen müssen das gleiche Problem lösen, ein Array ohne leere Slots erstellen, die alle Werte enthalten, und diese zurückgeben.

Wenn Sie die Flexibilität benötigen und eine ausreichend große Liste erstellen können, die Sie zum Übergeben verwenden können, tun Sie dies. Verwenden Sie andernfalls ein Array und geben Sie das threadsichere Objekt frei. Mit dem neuen Span können Sie auch Daten gemeinsam nutzen, ohne die Listen kopieren zu müssen.

Um die Frage zu beantworten:

Array.Resize(ref myArray, myArray.Length + 1);
data[myArray.Length - 1] = Value;
Walter Vehoeven
quelle
4

Wenn Sie also ein vorhandenes Array haben, ist meine schnelle Lösung

var tempList = originalArray.ToList();
tempList.Add(newitem);

Ersetzen Sie jetzt einfach das ursprüngliche Array durch das neue

originalArray = tempList.ToArray();
Adi_Pithwa
quelle
Ich habe meine Lösung gelöst
Praguanischer
3

Eine neue Append<TSource>Methode wurde hinzugefügtIEnumerable<TSource>Seit .NET Framework 4.7.1 und .NET Core 1.0 wurde .

So verwenden Sie es:

var numbers = new [] { "one", "two", "three" };
numbers = numbers.Append("four").ToArray();
Console.WriteLine(string.Join(", ", numbers)); // one, two, three, four

Beachten Sie, dass Sie Prepend<TSource>stattdessen die neue Methode verwenden können, wenn Sie das Element am Anfang des Arrays hinzufügen möchten .

0xced
quelle
2

Die Verwendung einer Liste ist die beste Option für die Speicherverwaltung.

Axxelsian
quelle
2

Was ist mit einer Erweiterungsmethode? Zum Beispiel:

public static IEnumerable<TSource> Union<TSource>(this IEnumerable<TSource> source, TSource item)
{
    return source.Union(new TSource[] { item });
}

zum Beispiel:

string[] sourceArray = new []
{
    "foo",
    "bar"
}
string additionalItem = "foobar";
string result = sourceArray.Union(additionalItem);

Beachten Sie, dass dies das Verhalten der Uniion-Erweiterung von Linq nachahmt (mit der zwei Arrays zu einem neuen kombiniert werden), und dass die Linq-Bibliothek funktionieren muss.

Wilhelm
quelle
1

Ich stimme Ed zu. C # macht dies nicht so einfach wie VB mit ReDim Preserve. Ohne eine Sammlung müssen Sie das Array in ein größeres kopieren.

Harpo
quelle
2
Danke Gott! ReDim ist unglaublich langsam, wenn es missbraucht wird. =)
Ed S.
ReDim PreserveKopiert das Array einfach in ein größeres. Es gibt keine wundersame Größenänderung des Arrays.
Olivier Jacot-Descombes
1
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();
Gia Duong Duc Minh
quelle
0
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;
    }
Dave Blake
quelle
0

Leider funktioniert die Verwendung einer Liste nicht in allen Situationen. Eine Liste und ein Array unterscheiden sich tatsächlich und sind nicht zu 100% austauschbar. Es würde von den Umständen abhängen, ob dies eine akzeptable Lösung wäre.

KRUG
quelle
0

Da diese Frage mit der angegebenen Antwort nicht zufrieden ist, möchte ich diese Antwort hinzufügen :)

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;  
    } 
  }
 }
}
Saif
quelle