Aggiungi nuovo elemento nell'array esistente in c # .net


134

Come aggiungere un nuovo elemento nell'array di stringhe esistente in C # .net?

Devo conservare i dati esistenti.

Risposte:


121

Vorrei utilizzare un elenco se hai bisogno di un array di dimensioni dinamiche:

List<string> ls = new List<string>();
ls.Add("Hello");

27
E se necessario, esegui ls.ToArray () alla fine
Narayana,

2
L'uso di un meccanico diverso da quello posto nella domanda non è una risposta.
user11909,

@ user2190035: Non sei sicuro di dove ti sia venuta quell'idea e le 111 persone che hanno votato non sarebbero d'accordo con te. Se conosci un modo migliore per espandere un array, allora pubblicalo. Dubito che la tua riassegnazione e la copia manuale saranno migliori rispetto all'utilizzo di un elenco. A volte la risposta è "non farlo".
Ed S.

@ EdS. La domanda era: come aggiungere un elemento a un array di stringhe esistente , ma questa risposta non ha alcun array, invece crea un nuovo Elenco <>. Nella mia applicazione, non riesco a cambiare il tipo in Elenco <>, quindi devo ridimensionare un array (fare una copia ...). La risposta di Ali Ersöz mi ha aiutato.
user11909,

@ user2190035: IEnumerable <T> .ToArray (). Scrivo C # ogni giorno e non ho mai dovuto ridimensionare un array come quello.
Ed S.

100

Potrebbe essere una soluzione;

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

Ma per array di dimensioni dinamiche preferirei anche l'elenco.


@Konrad, che sicuramente manterrà i dati nell'array.
Ali Ersöz,

1
questo non è adatto per più di qualche tempo invocando. perché la funzione 'Ridimensiona' ha prestazioni enormi. bug per una o due volte, questo è molto buono.
annuncio

53

Utilizzando LINQ:

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

Mi piace usare questo in quanto è un singolo e molto comodo da incorporare in un'istruzione switch, una semplice istruzione if o passare come argomento.

MODIFICARE:

Ad alcune persone non piace new[] { newitem }perché crea un array temporaneo di piccole dimensioni con un solo elemento. Ecco una versione Enumerable.Repeatche utilizza che non richiede la creazione di alcun oggetto (almeno non in superficie - gli iteratori .NET probabilmente creano un gruppo di oggetti macchina a stati sotto la tabella).

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

E se sei sicuro che l'array non nulldebba mai iniziare, puoi semplificarlo per:

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

Si noti che se si desidera aggiungere elementi a una raccolta ordinata, Listè probabilmente la struttura di dati desiderata, non un array con cui iniziare.


1
+1 molto bello. Ho un codice simile come metodo di estensione generico. Ho incluso il codice in questa risposta: stackoverflow.com/a/11035286/673545
dblood

Questo è molto utile trovandolo durante la ricerca di "come aggiungere ad un array in una riga di codice in c #" - si spera che questo commento sia sufficiente per ritrovarlo la prossima volta.
gary,

28

Domanda molto vecchia, ma volevo ancora aggiungere questo.

Se stai cercando un one-liner, puoi usare il codice qui sotto. Combina il costruttore di elenchi che accetta una sintassi enumerabile e "nuova" (dalla domanda sollevata).

myArray = new List<string>(myArray) { "add this" }.ToArray();

27

Array in C # sono immutabili , ad esempio string[], int[]. Ciò significa che non puoi ridimensionarli. Devi creare un nuovo array.

Ecco il codice per 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;
    }
}

Come puoi vedere, crea un nuovo array con le nuove dimensioni, copia il contenuto dell'array di origine e imposta il riferimento al nuovo array. Il suggerimento per questo è la parola chiave ref per il primo parametro.

Esistono elenchi che possono allocare dinamicamente nuovi slot per nuovi elementi. Questo è ad esempio Elenco <T> . Questi contengono array immutabili e li ridimensionano quando necessario (Elenco <T> non è un'implementazione dell'elenco collegato!). ArrayList è la stessa cosa senza Generics (con array di oggetti ).

LinkedList <T> è una vera implementazione dell'elenco dei collegamenti. Sfortunatamente puoi aggiungere solo elementi LinkListNode <T> all'elenco, quindi devi avvolgere i tuoi elementi di elenco in questo tipo di nodo. Penso che il suo uso sia raro.


Penso che tu abbia inteso Array.Copy
user123456

2
Solo una risposta che fornisce alcune informazioni sul perché non è possibile e non suggerisce solo di usare un elenco ...
Gilad Green

Credo che Aray.Resizepossa ridimensionare un array senza perdere il suo contenuto. docs.microsoft.com/en-us/dotnet/api/…
AbdelAziz AbdelLatef

25
 Array.Resize(ref youur_array_name, your_array_name.Length + 1);
 your_array_name[your_array_name.Length - 1] = "new item";

7

Puoi espandere la risposta fornita da @Stephen Chung usando la sua logica basata su LINQ per creare un metodo di estensione usando un tipo generico.

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

}

È quindi possibile chiamarlo direttamente sull'array in questo modo.

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

Certo, il metodo AddRangeToArray () sembra un po 'eccessivo poiché hai la stessa funzionalità con Concat () ma in questo modo il codice finale può "funzionare" con l'array direttamente al contrario:

options = options.Concat(new string[] { "one", "two", "three" }).ToArray();

Grazie, questo è stato molto utile, ho aggiunto un'opzione per rimuovere un elemento (spero che questo vada bene per te).
Tal Segal,

@TalSegal sei il benvenuto, piacere mio. Usa il codice come ritieni opportuno!
Dblood,

6

È meglio mantenere l'array immutabile e di dimensioni fisse.

puoi simulare Addcon Extension MethodeIEnumerable.Concat()

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

5

se si lavora molto con array e non elenchi per qualche motivo, questo metodo generico restituito tipizzato Addpotrebbe essere utile

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

4

Tutte le risposte proposte fanno lo stesso di quello che dicono che vorrebbero evitare, creando un nuovo array e aggiungendo una nuova voce in esso solo con un overhead maggiore perso. LINQ non è magico, l'elenco di T è un array con uno spazio buffer con un po 'di spazio in più per evitare di ridimensionare l'array interno quando vengono aggiunti elementi.

Tutte le astrazioni devono risolvere lo stesso problema, creare un array senza slot vuoti che contenga tutti i valori e li restituisca.

Se hai bisogno della flessibilità, puoi creare un elenco abbastanza grande che puoi usare per passare, quindi fallo. altrimenti usa un array e condividi quell'oggetto thread-safe. Inoltre, il nuovo Span aiuta a condividere i dati senza dover copiare gli elenchi.

Per rispondere alla domanda:

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

4

Quindi, se hai un array esistente, la mia soluzione rapida sarà

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

Ora basta sostituire l'array originale con quello nuovo

originalArray = tempList.ToArray();

Risolto la mia soluzione
praguan

3

È Append<TSource>stato aggiunto un nuovo metodoIEnumerable<TSource> partire da .NET Framework 4.7.1 e .NET Core 1.0 .

Ecco come usarlo:

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

Se si desidera aggiungere l'elemento all'inizio dell'array, è possibile utilizzare invece il nuovo Prepend<TSource>metodo.


2

L'uso di un elenco sarebbe l'opzione migliore per la gestione della memoria.


2

Che dire dell'utilizzo di un metodo di estensione? Per esempio:

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

per esempio:

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

Nota: questo imita questo comportamento dell'estensione Uniion di Linq (usato per combinare due array in uno nuovo) e richiedeva il funzionamento della libreria Linq.


1

Sono d'accordo con Ed. C # non lo rende facile come VB con ReDim Preserve. Senza una raccolta, dovrai copiare l'array in uno più grande.


2
Grazie Dio! ReDim è incredibilmente lento se abusato. =)
Ed S.

ReDim Preservecopia semplicemente l'array in uno più chiaro. Non esiste un ridimensionamento miracoloso dell'array.
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();

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


0

Sfortunatamente l'uso di un elenco non funzionerà in tutte le situazioni. Un elenco e un array sono in realtà diversi e non sono intercambiabili al 100%. Dipenderebbe dalle circostanze se questa sarebbe una soluzione accettabile.


0

Poiché questa domanda non è soddisfatta della risposta fornita, vorrei aggiungere questa risposta :)

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;  
    } 
  }
 }
}
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.