在 C# 中弹出数组

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/455237/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-04 04:01:57  来源:igfitidea点击:

Pop off array in C#

c#arrays

提问by robintw

I've got a string array in C# and I want to pop the top element off the array (ie. remove the first element, and move all the others up one). Is there a simple way to do this in C#? I can't find an Array.Pop method.

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

Would I need to use something like an ArrayList? The order of the items in my array is important.

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

采纳答案by driAn

Use a List, Queueor Stackinstead..

改用ListQueueStack..

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

回答by Paul Lefebvre

From MSDN:

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

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

回答by Jon Skeet

Queue<T>(first in, first out) or Stack<T>(last in, first out) are what you're after.

Queue<T>(先进先出)或Stack<T>(后进先出)是您所追求的。

Arrays in .NET are fixed length - you can't remove an element from them or indeed add elements to them. You cando this with a List<T>but Queue<T>and Stack<T>are more appropriate when you want queue/stack semantics.

.NET 中的数组是固定长度的——你不能从它们中删除一个元素,也不能向它们添加元素。你可以用一个做到这一点List<T>,但Queue<T>Stack<T>是当你想队列/堆栈语义比较合适。

回答by Michael Blackburn

I ran into the concern I noted above but had problems with Queue's default behavior of throwing an exception when the collection was empty (not really an exceptional situation). This is my implementation of a SafeQueue, which will defer most operations to the base class, but implements new Dequeue()and Peek()operations that return default(T)if the queue is empty. In cases where it is possible default(T)was added to the queue (unlikely for object types, but very likely for value types), it is impossible to tell if the queue is empty just with Peek. A new IsEmptyproperty makes it possible to tell when you're done.

我遇到了上面提到的问题,但是当集合为空时,Queue 的默认行为抛出异常(不是真正的异常情况)存在问题。这是我对 SafeQueue 的实现,它将大多数操作推迟到基类,但实现了如果队列为空则返回的newDequeue()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);
    }

}

回答by harsimranb

This is entirely possible in Array, but it is not efficient. You literally have to shift down your array using a loop and setting arr[i] = arr[i+1] in a for loop. After this, if you want, you have to resize the array.

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

Because of these caveats, array isn't the best data structure to deal with problem. Array is best for static data, or data whose size will not change.

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

Since you want to remove data, array is clearly not the answer. Specifically, you want to pop the first/top element from your collection, and there is already an efficient data structure that does this: Stack.

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

This is the beauty of data structures, they give you an efficient way to deal with your collections based on what your requirements are.

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

回答by Arturo Menchaca

Since we have linqis very easy to do:

由于我们有linq很容易做到:

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

回答by Assil

I agree on the above, but I have a little enhancement..

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

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

And to make it complete, here is the 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()));
        }

回答by Pellet

What you actually want is called a Queue, you can create a Queue from your Array like so:

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

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

回答by Markus

For completeness, this is also fast;

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

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