Всплывающий массив в C # - PullRequest
       51

Всплывающий массив в C #

22 голосов
/ 18 января 2009

У меня есть строковый массив в C #, и я хочу вытолкнуть верхний элемент из массива (т.е. удалить первый элемент и переместить все остальные вверх на один). Есть ли простой способ сделать это в C #? Я не могу найти метод Array.Pop.

Нужно ли мне использовать что-то вроде ArrayList? Порядок элементов в моем массиве важен.

Ответы [ 8 ]

32 голосов
/ 18 января 2009

Queue<T> (первый пришел, первый вышел) или Stack<T> (последний пришел, первый вышел) - это то, что вам нужно.

Массивы в .NET имеют фиксированную длину - вы не можете удалить из них элемент или добавить элементы к ним. Вы можете сделать это с List<T>, но Queue<T> и Stack<T> более подходят, когда вы хотите использовать семантику очереди / стека.

31 голосов
/ 18 января 2009

Вместо Список , Очередь или Стек вместо ..

List<String>
Queue<String>
Stack<String>
12 голосов
/ 18 января 2009

Из 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/

5 голосов
/ 12 апреля 2016

Поскольку у нас есть linq , это очень легко сделать:

string[] array = ...;
array = array.Skip(1).ToArray();
1 голос
/ 22 сентября 2016

Я согласен с вышесказанным, но у меня есть небольшое улучшение ..

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

И чтобы завершить, вот тест:

  [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 голос
/ 12 апреля 2016

Это полностью возможно в массиве, но это не эффективно. Вы буквально должны сдвинуть свой массив, используя цикл и установив arr [i] = arr [i + 1] в цикле for. После этого, если вы хотите, вы должны изменить размер массива.

Из-за этих предостережений массив не лучшая структура данных для решения проблемы. Массив лучше всего подходит для статических данных или данных, размер которых не изменится.

Поскольку вы хотите удалить данные, массив явно не является ответом. В частности, вы хотите извлечь первый / верхний элемент из вашей коллекции, и уже существует эффективная структура данных, которая делает это: Stack .

В этом прелесть структур данных, они дают вам эффективный способ работы с вашими коллекциями на основе ваших требований.

1 голос
/ 12 апреля 2016

Я столкнулся с проблемой, о которой упоминал выше, но у меня были проблемы со стандартным поведением в очереди, выдававшим исключение, когда коллекция была пустой (на самом деле это не исключительная ситуация). Это моя реализация SafeQueue, которая откладывает большинство операций до базового класса, но реализует новые операции Dequeue() и Peek(), которые возвращают default(T), если очередь пуста. В тех случаях, когда возможно добавление default(T) в очередь (маловероятно для типов объектов, но очень вероятно для типов значений), невозможно определить, является ли очередь пустой только с помощью Peek. Новое свойство IsEmpty позволяет узнать, когда вы закончите.

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

}
0 голосов
/ 06 апреля 2017

То, что вы на самом деле хотите, называется очередью, вы можете создать очередь из вашего массива следующим образом:

var args = { "value1", "value2" };
var queue = new Queue<string>(args);
var arg1 = queue.Dequeue();
var arg2 = queue.Dequeue();
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...