web-dev-qa-db-fra.com

Pop off array en C #

J'ai un tableau de chaînes en C # et je veux extraire le premier élément du tableau (c.-à-d. Supprimer le premier élément et déplacer tous les autres vers le haut). Existe-t-il un moyen simple de faire cela en C #? Je ne trouve pas de méthode Array.Pop.

Aurais-je besoin d'utiliser quelque chose comme une ArrayList? L'ordre des éléments de mon tableau est important.

21
robintw

Utilisez une liste , file d'attente ou pile à la place.

List<String>
Queue<String>
Stack<String>
31
driAn

Queue<T> (premier entré, premier sorti) ou Stack<T> (dernier entré, premier sorti) correspond à ce que vous recherchez.

Les tableaux dans .NET ont une longueur fixe. Vous ne pouvez pas leur en retirer un élément, ni même leur ajouter. Vous pouvez faites cela avec un List<T> mais Queue<T> et Stack<T> sont plus appropriés lorsque vous voulez une sémantique file/stack.

32
Jon Skeet

De MSDN:

using System;
using System.Collections.Generic;

namespace ConsoleApplication1
{
    class MSDNSample
    {
       static void Main()
       {
          string input = "a b c d";

          Stack<string> myStack = new Stack<string>(
             input.Split(new string[] { " " }, StringSplitOptions.None));

          // Remove the top element (will be d!)
          myStack.Pop();

          Queue<string> myQueue = new Queue<string>(

          input.Split(new string[] { " " }, StringSplitOptions.None));

          // Remove the first element (will be a!)
          myQueue.Dequeue();

       }
    }
}

http://social.msdn.Microsoft.com/Forums/en-US/csharplanguage/thread/a924097e-3d72-439d-984a-b371cd10bcf4/

12
Paul Lefebvre

Puisque nous avons linq c'est très facile à faire:

string[] array = ...;
array = array.Skip(1).ToArray();
3
Arturo Menchaca

C'est tout à fait possible dans Array, mais ce n'est pas efficace. Vous devez littéralement décaler votre tableau en utilisant une boucle et en définissant arr [i] = arr [i + 1] dans une boucle for. Après cela, si vous voulez, vous devez redimensionner le tableau.

En raison de ces mises en garde, array n'est pas la meilleure structure de données pour traiter les problèmes. La matrice est préférable pour les données statiques, ou les données dont la taille ne changera pas.

Puisque vous voulez supprimer des données, array n’est clairement pas la solution. Spécifiquement, vous voulez extraire le premier/top élément de votre collection et il existe déjà une structure de données efficace qui fait cela: Stack .

C'est la beauté des structures de données, elles vous offrent un moyen efficace de gérer vos collections en fonction de vos besoins.

1
harsimranb

J'ai rencontré l'inquiétude que j'ai notée ci-dessus, mais le comportement par défaut de Queue qui consistait à lever une exception lorsque la collection était vide était problématique (cette situation n'était pas vraiment exceptionnelle). Ceci est mon implémentation d'une SafeQueue, qui reportera la plupart des opérations à la classe de base, mais implémentera les nouvelles opérations Dequeue() et Peek() qui retournent default(T) si la file d'attente est vide. Dans les cas où il est possible que default(T) ait été ajouté à la file d'attente (peu probable pour les types d'objet, mais très probablement pour les types valeur), il est impossible d'indiquer si la file est vide uniquement avec Peek. Une nouvelle propriété IsEmpty permet de dire quand vous avez terminé.

public class SafeQueue<T>: Queue<T>
{
    public SafeQueue() : base() { }

    public SafeQueue(int count) : base(count) { }

    public SafeQueue(IEnumerable<T> collection) : base(collection) { }

    public bool IsEmpty {get { return Count == 0; }}

    public new T Dequeue()
    {
        return IsEmpty ? default(T) : base.Dequeue();
    }

    public new T Peek()
    {
        return IsEmpty ? default(T) : base.Peek();
    }
}


[TestClass]
public class SafeQueueTests
{
    [TestMethod]
    public void SafeQueue_int_constructor_works()
    {
        var q = new SafeQueue<string>(5);
        Assert.IsNotNull(q);
        Assert.AreEqual(0, q.Count);
        q.Enqueue("a");
        Assert.AreEqual(1, q.Count);
        q.Enqueue("b");
        Assert.AreEqual(2, q.Count);
        q.Enqueue("c");
        Assert.AreEqual(3, q.Count);
        q.Enqueue("d");
        Assert.AreEqual(4, q.Count);
        q.Enqueue("e");
        Assert.AreEqual(5, q.Count);
        q.Enqueue("f");
        Assert.AreEqual(6, q.Count);
    }

    [TestMethod]
    public void SafeQueue_dequeue_works()
    {
        var q = new SafeQueue<string>();
        Assert.IsNotNull(q);
        Assert.AreEqual(0, q.Count);
        q.Enqueue("a");
        Assert.AreEqual(1, q.Count);
        q.Enqueue("b");
        Assert.AreEqual(2, q.Count);
        var result = q.Dequeue();
        Assert.AreEqual("a", result);
        result = q.Dequeue();
        Assert.AreEqual("b", result);
        result = q.Dequeue();
        Assert.AreEqual(null, result);
    }
    [TestMethod]
    public void SafeQueue_peek_works()
    {
        var q = new SafeQueue<string>();
        Assert.IsNotNull(q);
        Assert.AreEqual(0, q.Count);
        q.Enqueue("a");
        Assert.AreEqual(1, q.Count);
        var result = q.Peek();
        Assert.AreEqual("a", result);
        result = q.Dequeue();
        Assert.AreEqual("a", result);
        result = q.Dequeue();
        Assert.AreEqual(null, result);
    }

    [TestMethod]
    public void SafeQueue_isEmpty_works()
    {
        var q = new SafeQueue<string>();
        Assert.IsNotNull(q);
        Assert.AreEqual(0, q.Count);
        Assert.AreEqual(true, q.IsEmpty);
        q.Enqueue("content");
        Assert.AreEqual(false, q.IsEmpty);
        var result2 = q.Dequeue();
        Assert.AreEqual("content", result2);
        Assert.AreEqual(true, q.IsEmpty);
        result2 = q.Dequeue();
        Assert.AreEqual(true, q.IsEmpty);
        Assert.AreEqual(null, result2);
    }
    [TestMethod]
    public void SafeQueue_passedThroughQueueOperationContains_work()
    {
        var q = new SafeQueue<string>(5);
        Assert.IsNotNull(q);
        Assert.AreEqual(0, q.Count);
        q.Enqueue("a");
        Assert.AreEqual(1, q.Count);
        q.Enqueue("b");
        Assert.AreEqual(2, q.Count);
        q.Enqueue("c");
        Assert.AreEqual(3, q.Count);
        Assert.IsTrue(q.Contains("a"));
        Assert.IsFalse(q.Contains("asdfawe"));
        var outval = q.Dequeue();
        Assert.IsFalse(q.Contains("a"));
    }
    [TestMethod]
    public void SafeQueue_CantTellByDequeueIfQueueIsEmptyOrContainsNull()
    {
        var q = new SafeQueue<string>();
        Assert.IsNotNull(q);
        Assert.AreEqual(true, q.IsEmpty);
        q.Enqueue(null);
        Assert.AreEqual(false, q.IsEmpty);
        var result2 = q.Peek();
        Assert.AreEqual(null, result2);
        Assert.AreEqual(false, q.IsEmpty);
        result2 = q.Dequeue();
        Assert.AreEqual(true, q.IsEmpty);
        Assert.AreEqual(null, result2);
    }

}
1
Michael Blackburn

Je suis d'accord sur ce qui précède, mais j'ai une petite amélioration .. 

  public static class ArrayExtensions
    {
        /// <summary>
        /// Removes the last element.
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="array">The array.</param>
        /// <returns>T[].</returns>
        public static T[] RemoveLastElement<T>(this T[] array)
        {
            var stack = new Stack<T>(array);
            stack.Pop();
            return stack.ToArray().Reverse().ToArray();
        }

        /// <summary>
        /// Removes the first element.
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="array">The array.</param>
        /// <returns>T[].</returns>
        public static T[] RemoveFirstElement<T>(this T[] array)
        {
            var queue = new Queue<T>(array);
            queue.Dequeue();
            return queue.ToArray();
        }
    }

Et pour le rendre complet, voici le test:

  [Test]
        public void ExtensionsTests_ArrayExtensionTests()
        {
            var data = new[] { 'A', 'B', 'C', 'D' };

            Assert.AreEqual("BCD", string.Join("", data.RemoveFirstElement()));
            Assert.AreEqual("ABC", string.Join("", data.RemoveLastElement()));
        }
1
Assil

Ce que vous voulez réellement s'appelle une file d'attente, vous pouvez créer une file d'attente à partir de votre tableau comme suit:

var args = { "value1", "value2" };
var queue = new Queue<string>(args);
var arg1 = queue.Dequeue();
var arg2 = queue.Dequeue();
0
Pellet