在C#中弹出数组

时间:2009-01-18 14:41:40

标签: c# arrays

我在C#中有一个字符串数组,我想从数组中弹出顶部元素(即删除第一个元素,然后将所有其他元素向上移动)。在C#中有一种简单的方法吗?我找不到Array.Pop方法。

我需要使用像ArrayList这样的东西吗?我的数组中项目的顺序很重要。

10 个答案:

答案 0 :(得分:32)

Queue<T>(先进先出)或Stack<T>(进去,先出)是您的目标。

.NET中的数组是固定长度的 - 您无法从中删除元素或确实向它们添加元素。您可以使用List<T>执行此操作,但Queue<T>Stack<T>更适合您需要队列/堆栈语义。

答案 1 :(得分:31)

使用ListQueueStack代替..

List<String>
Queue<String>
Stack<String>

答案 2 :(得分:12)

来自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/

答案 3 :(得分:5)

由于我们 linq 很容易做到:

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

答案 4 :(得分:1)

我遇到了上面提到的问题但遇到了Queue在集合为空时抛出异常的默认行为的问题(并非真正特殊的情况)。这是我对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);
    }

}

答案 5 :(得分:1)

这在Array中是完全可能的,但效率不高。你必须使用循环向下移动数组并在for循环中设置arr [i] = arr [i + 1]。在此之后,如果需要,您必须调整阵列的大小。

由于这些警告,数组不是处理问题的最佳数据结构。数组最适合静态数据或大小不会改变的数据。

由于您要删除数据,因此数组显然不是答案。具体来说,您希望从集合中弹出第一个/顶部元素,并且已经有一个高效的数据结构可以执行此操作:Stack

这是数据结构的美妙之处,它们为您提供了一种根据您的要求处理您的馆藏的有效方式。

答案 6 :(得分:1)

我同意上述内容,但我有一点改进..

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

答案 7 :(得分:0)

你真正想要的是一个队列,你可以从你的数组创建一个队列,如下所示:

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

答案 8 :(得分:0)

为了完整起见,这也很快;

    /// <summary>
    /// Pop value from top of string[] array
    /// </summary>
    public void PopStringArray(ref string[] array)
    {
        int newLength = array.Length;
        string[] temp = new string[array.Length];

        for (int i = array.Length - 1; i >= 1; i--)
            temp[i - 1] = array[i];

        array = temp;
    }

答案 9 :(得分:0)

以防万一有人遇到这种情况,pop() 函数类似于打字稿中的函数,即从数组中弹出最后一项并返回其值

    public static T Pop<T>(this IList<T> collection) where T : class
    {
        if (collection == null || !collection.Any())
        {
            throw new ArgumentException($"Failed to pop list of {typeof(T)}, cannot be empty or null");
        }

        var lastItemAsJson = JsonSerializer.Serialize(collection.Last());
        collection.Remove(collection.Last());
        return JsonSerializer.Deserialize<T>(lastItemAsJson);
    }