【问题标题】:How to "Dequeue" Element from a List?如何从列表中“出列”元素?
【发布时间】:2014-07-20 23:28:16
【问题描述】:

我有一张名为 _deck 的 List 卡片:

 private List<String> _deck = new List<String> {"2h", "3h", "4h", ... }

然后我想从List 中删除一张卡片并保存到一个变量中。我正在尝试:

 String p1FirstCard = _deck.RemoveAt(0);

但我得到了错误

无法将类型 void 转换为字符串

在 C# List 中是否有类似 push/pop 的东西,但它在 List 的“头部”或“开始”处执行此操作? (Push/pop 作用于列表的“尾部”或“末尾”。)

如果没有,我应该如何删除第一个元素并将其保存在变量中?

【问题讨论】:

  • 为什么不使用 Queue 来代替?
  • 看起来您的卡片列表名为“_deck”

标签: c# arrays


【解决方案1】:

如果你想使第一个元素出队,你可以简单地使用Queue&lt;T&gt;

class Program
{
    static void Main(string[] args)
    {
        var _deck = new Queue<String>();
        _deck.Enqueue("2h");
        _deck.Enqueue("3h");
        _deck.Enqueue("4h");
        _deck.Enqueue("...");

        var first = _deck.Dequeue(); // 2h
        first = _deck.Dequeue(); // 3h
    }
}

如果要弹出最后一个元素,可以使用Stack&lt;T&gt;

class Program
{
    static void Main(string[] args)
    {
        var _deck = new Stack<String>();
        _deck.Push("2h");
        _deck.Push("3h");
        _deck.Push("4h");
        _deck.Push("...");

        var first = _deck.Pop(); // ...
        first = _deck.Pop(); // 4h
    }
}

【讨论】:

  • 您的意思可能是通用版本:msdn.microsoft.com/en-us/library/7977ey2c.aspx
  • C# 堆栈或队列都不会从列表的 end 中删除,这就是 actionscript 的 pop() 的工作原理。并不意味着它们不是正确的选择,只是两者都不是完美的匹配。
  • @Bobson,我确实再次阅读了这个问题以确保我没有错,但他在哪里要求删除最后一个问题?代码显示第一个元素只被删除
  • @Fredou - OP 没有,但由于他引用了pop(),我认为这是他所期望的行为。
  • Pop 和 Dequeue 确实从列表的末尾删除。见这里:msdn.microsoft.com/en-us/library/… 或这里msdn.microsoft.com/en-us/library/1c8bzx97(v=vs.110).aspx
【解决方案2】:

您可以分两步完成:

String p1FirstCard = _deck[0];
_deck.RemoveAt(0);

您可以编写自己的扩展助手方法(我在Pop 中添加了一个索引,正如@Fredou 建议的那样:

static class ListExtension
{
    public static T PopAt<T>(this List<T> list, int index)
    {
        T r = list[index];
        list.RemoveAt(index);
        return r;
    }
}

然后调用

String p1FirstCard = _deck.PopAt(0);

附: 名称可能有点混乱。 Pop 通常会删除最后一个元素,而不是第一个。

【讨论】:

  • 也许您应该更改代码以使用参数按索引返回/删除项目,这将为 OP 提供所有可能的选择
  • 不错。对于一个洗牌的套牌,我是从套牌的顶部还是底部拉出来真的无关紧要,所以这太棒了。谢谢。
  • 您还可以在方法声明中添加index = 0,将第一个元素作为默认操作删除,避免传递index参数。我认为这很有用,因为您通常希望删除第一个元素。
【解决方案3】:

如果您想要直接等效于pop(),则必须自己编写,因为我认为List 没有“从结尾删除并返回”。但是,有Queue(先进先出)和Stack(先进后出)类,而不仅仅是List

还有 LinkedList 类,它允许您从开头或结尾添加或删除,但提供的 RemoveFirst()RemoveLast() 方法不会自动返回要删除的项目 - 您需要编写一个类似 AlexD 的扩展方法来做到这一点。

所有这些都涉及从列表的开头或结尾删除内容。如果您只想从 List 的中间删除任意项目,则始终有 List.Remove(item) 从列表中删除特定项目(而不是按位置)。

【讨论】:

    【解决方案4】:

    AlexD's answer 的基础上,我添加了几个扩展方法:

    public static class ListExtensionMethods
    {
        public static T PopAt<T>(this List<T> list, int index)
        {
            var r = list[index];
            list.RemoveAt(index);
            return r;
        }
    
        public static T PopFirst<T>(this List<T> list, Predicate<T> predicate)
        {
            var index = list.FindIndex(predicate);
            var r = list[index];
            list.RemoveAt(index);
            return r;
        }
    
        public static T PopFirstOrDefault<T>(this List<T> list, Predicate<T> predicate) where T : class
        {
            var index = list.FindIndex(predicate);
            if (index > -1)
            {
                var r = list[index];
                list.RemoveAt(index);
                return r;
            }
            return null;
        }
    }
    

    【讨论】:

      【解决方案5】:
       private List<String> _deck = new List<String> {"2h", "3h", "4h", ... }
       //Save into variable first
       String p1FirstCard = _deck[0];
       //Now just remove it
       _deck.RemoveAt(0);
      

      RemoveAt(int) 不返回任何内容。

      【讨论】:

        猜你喜欢
        • 2022-01-06
        • 2021-03-10
        • 2014-12-16
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多