web-dev-qa-db-fra.com

Ajouter un nouvel élément dans un tableau existant dans c # .net

Comment ajouter un nouvel élément dans un tableau de chaînes existant dans C # .net?

J'ai besoin de préserver les données existantes.

112
Nirmal

Je voudrais utiliser une liste si vous avez besoin d'un tableau de taille dynamique:

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

Cela pourrait être une solution.

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

Mais pour un tableau de taille dynamique, je préférerais aussi une liste.

87
Ali Ersöz

Utiliser LINQ:

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

J'aime utiliser ceci car il s'agit d'un one-liner et il est très pratique de l'intégrer dans une instruction switch, une simple instruction if ou de la passer en argument.

MODIFIER:

Certaines personnes n'aiment pas new[] { newitem } car cela crée un petit tableau temporaire à un élément. Voici une version utilisant Enumerable.Repeat qui ne nécessite de créer aucun objet (du moins pas sur la surface - les itérateurs .NET créent probablement un tas d’objets de machine à états sous la table).

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

Et si vous êtes sûr que le tableau n'est jamais null pour commencer, vous pouvez le simplifier pour:

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

Notez que si vous souhaitez ajouter des éléments à une collection ordonnée, List correspond probablement à la structure de données souhaitée et non à un tableau.

48
Stephen Chung

Les tableaux en C # sont immuables , par exemple. string[], int[]. Cela signifie que vous ne pouvez pas les redimensionner. Vous devez créer un nouveau tableau.

Voici le code pour 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;
    }
}

Comme vous pouvez le constater, il crée un nouveau tableau avec la nouvelle taille, copie le contenu du tableau source et définit la référence sur le nouveau tableau. L'indice pour cela est le mot clé ref pour le premier paramètre.

Il existe des listes qui peuvent allouer dynamiquement de nouveaux créneaux horaires pour de nouveaux éléments. C'est par exemple Liste <T>. Ceux-ci contiennent des tableaux immuables et les redimensionnent si nécessaire (La liste <T> n'est pas une implémentation de liste chaînée!). ArrayList est la même chose sans Generics (avec le tableau Object).

LinkedList <T> est une implémentation réelle de la liste chaînée. Malheureusement, vous ne pouvez ajouter que des éléments LinkListNode <T> à la liste. Vous devez donc inclure vos propres éléments de liste dans ce type de nœud. Je pense que son utilisation est rare.

23
artur02

Très vieille question, mais je voulais toujours ajouter ceci.

Si vous recherchez une ligne, vous pouvez utiliser le code ci-dessous. Il combine le constructeur de liste qui accepte une énumération énumérable et la syntaxe d'initialisation "new" (depuis la question posée).

myArray = new List<string>(myArray) { "add this" }.ToArray();
21
 Array.Resize(ref youur_array_name, your_array_name.Length + 1);
 your_array_name[your_array_name.Length - 1] = "new item";
19
tmania

Vous pouvez développer la réponse fournie par @Stephen Chung en utilisant sa logique basée sur LINQ pour créer une méthode d'extension utilisant un type générique.

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

}

Vous pouvez ensuite l'appeler directement sur le tableau comme ceci.

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

Certes, la méthode AddRangeToArray () semble un peu exagérée puisque vous avez la même fonctionnalité que Concat (), mais de cette façon, le code de fin peut "fonctionner" avec le tableau directement.

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

si vous travaillez beaucoup avec des tableaux et pas des listes pour une raison quelconque, cette méthode générique de retour générique de type Add pourrait vous aider

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

Il est préférable de garder Array immuable et de taille fixe.

vous pouvez simuler Add par Extension Method et IEnumerable.Concat()

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

L'utilisation d'une liste serait votre meilleure option pour la gestion de la mémoire.

2
Axxelsian

Toutes les réponses proposées font la même chose que ce qu’elles disent qu’elles aimeraient éviter, en créant un nouveau tableau et en y ajoutant une nouvelle entrée sans perdre plus de temps système. LINQ n’est pas magique, list of T est un tableau avec un espace tampon avec un espace supplémentaire afin d’éviter de redimensionner le tableau intérieur lorsque des éléments sont ajoutés. 

Toutes les abstractions doivent résoudre le même problème, créer un tableau sans emplacements vides contenant toutes les valeurs et les renvoyer. 

Si vous avez besoin de flexibilité, vous pouvez créer une liste assez longue que vous pouvez utiliser pour passer. sinon, utilisez un tableau et partagez cet objet thread-safe. En outre, la nouvelle Span permet de partager des données sans avoir à copier les listes. 

Pour répondre à la question:

Array.Resize(ref myArray, myArray.Length + 1);
data[myArray.Length - 1] = Value;
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();
1
Gia Duong Duc Minh

Je suis d'accord avec Ed. C # ne rend pas cela facile comme le fait VB avec ReDim Preserve. Sans collection, vous devrez copier le tableau dans un fichier plus grand.

1
harpo

Qu'en est-il de l'utilisation d'une méthode d'extension? Par exemple:

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

par exemple:

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

Notez que cela reproduit le comportement de l'extension Uniion de Linq (utilisé pour combiner deux tableaux dans un nouveau) et que la bibliothèque Linq devait fonctionner.

1
William

// Donc si vous avez un tableau existant

// ma solution rapide sera

var tempList = originalArray.ToList ();

tempList.Add (newitem);

// maintenant remplace simplement le tableau d'origine par le nouveau

originalArray = tempList.ToArray ();

0
Adi_Pithwa

Pourquoi ne pas essayer d’utiliser la classe Stringbuilder. Il a des méthodes telles que .insert et .append. Vous pouvez en savoir plus à ce sujet ici: http://msdn.Microsoft.com/en-us/library/2839d5h5(v=vs.71).aspx

0
aevanko
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
Dave Blake

Puisque cette question n'est pas satisfaite de la réponse fournie, j'aimerais ajouter cette réponse :)

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

Malheureusement, utiliser une liste ne fonctionnera pas dans toutes les situations. Une liste et un tableau sont en réalité différents et ne sont pas 100% interchangeables. Cela dépendrait des circonstances s'il s'agissait d'un travail acceptable.

0
JAR