zoukankan      html  css  js  c++  java
  • C# 便捷实现可迭代对象间的赋值

    都是迭代,为啥我一定要用foreach

    ​ 问题起源于本人的一个练手的扑克牌程序:洗完牌之后要发给场上的三人。
    ​ 只发给单个人的时候用 foreach 循环一下就好了,但三个人就有点麻烦了。
    ​ 牌组用list保存你可能会想到这样写:

                for (int i = 0; i < PreCard.Count; i++)
                {
                    a.Add(PreCard[i++]);
                    b.Add(PreCard[i++]);
                    c.Add(PreCard[i]);
                }
    

    ​ 或者这样写

                int i = 0;
                do
                {
                    a.Insert(i, PreCard[0]);
                    b.Insert(i, PreCard[1]);
                    c.Insert(i, PreCard[2]);
                    PreCard.RemoveRange(0, 3);
                    i++;
                } while (i < PreCard.Count);
    

    ​ 但如果还想使用类似迭代器的方法,那么可以使用 GetEnumerator(),因为我们知道 foreach 里面实际上就是调用了这个方法。
    ​ 所以我们还可以直接调用 GetEnumerator 和 MoveNext 来进行迭代:

                IEnumerator ie = PreCard.GetEnumerator();
                while(ie.MoveNext())
                {
                    a.Add(ie.Current.ToString());
                    ie.MoveNext();
                    b.Add(ie.Current.ToString());
                    ie.MoveNext(); 
                    c.Add(ie.Current.ToString());
                }
    

    如果换成是字典呢?

    ​ 如果是直接把上面的代码搬过来,会发现add方法那里会报错,需要提供两个参数,键和值。
    ​ 难道必须要对得到的 IEnumerator 再用一次 GetEnumerator?
    ​ 实际上大可不必,因为针对这种键值对,我们有一个玩意叫做 IDictionaryEnumerator。看名字就知道它就是为此而生的。

                IDictionaryEnumerator ie = dict.GetEnumerator();
                while(ie.MoveNext())
                {
                    a.Add(ie.Key.ToString(),Convert.ToInt32(ie.Value));
                    ie.MoveNext();
                    b.Add(ie.Key.ToString(),Convert.ToInt32(ie.Value));
                    ie.MoveNext();
                    c.Add(ie.Key.ToString(),Convert.ToInt32(ie.Value));
                }
    

    ​ 至此我们通过写手动挡的 foreach ,成功的实现了可迭代对象间的赋值。

    关于 foreach

    ​ 在C#中 foreach 语句,能够进行比for循环语句更直接和简单的对集合的迭代,编译器会将 foreach 编译来调用 GetEnumerator 和 MoveNext方法以及Current属性。

    ​ 实际上 foreach 语句编译之后也会产生类似于上面所写的代码。实际上这幅图可以比较清楚的说明一切。


    ​ 当然你也可以看看我写的这篇随笔,了解更多细节https://www.cnblogs.com/AD-milk/p/12459944.html

    务必看看这里

    ​ 其实前面的做法都是舍近求远....

    ​ 我一开始写的时候,觉得那样做还挺好的。甚至还自信满满的点了发送到首页[捂脸]
    ​ 然后....当然是马上就被撤了。我当然是不服的(声音减弱),于是就发邮件询问。
    ​ 结果当然就是被管理员教育了,其实管理员挺耐心,教会了我很多。(隔着屏幕我也不知道对面想不想顺着网线打我)
    ​ 如果你还想保留原来的集合的话,那么用上面的方法是可行的,如果不想的话,那么像下面那样使用linq 会更好。

    ​ 下面就给大家分享更正一下我学到的知识:

                var PreCard = new Queue<string>() ;
                PreCard.Enqueue("03a");
                PreCard.Enqueue("03b");
                PreCard.Enqueue("03c");
                PreCard.Enqueue("03d");
                PreCard.Enqueue("04a");
                PreCard.Enqueue("04b");
               
                var players = new List<List<string>>
                {
                    new List<string>(),
                    new List<string>(),
                    new List<string>()
                };
    
                while (PreCard.Count > 0)
                {
                    players.ForEach(p => p.Add(PreCard.Dequeue()));
                }
    
                players.ForEach(p =>
                {
                    p.ForEach(c => Console.Write(c + " "));
                    Console.WriteLine();
                });
    

    对于字典,可以使用KeyValuePair

                var PreCard = new Queue<KeyValuePair<string, int>>(
                    new Dictionary<string, int>
                    {
                        {"a",1 },{"b",2 },{"c",3 },{"d",4 },{"e",5 },{"f",6 }
                    });
                var players = new List<List<KeyValuePair<string, int>>>
                {
                     new List<KeyValuePair<string, int>>(),
                     new List<KeyValuePair<string, int>>(),
                     new List<KeyValuePair<string, int>>()
                };
    
                while (PreCard.Count > 0)
                {
                    players.ForEach(p => p.Add(PreCard.Dequeue()));
                }
    
                players.ForEach(p =>
                {
                    p.ForEach(c => Console.Write(c + " "));
                    Console.WriteLine();
                });
    

    可能各位早会这样弄了,让各位进来实在是不好意思了。

    最后说一句,linq真好用!

  • 相关阅读:
    Eclipse(MyEclipse)使用技巧——改动凝视字体大小
    C++标准库之 Lower_Bound, upper_Bound
    Mongodb地理空间索引
    AfxMessageBox和MessageBox差别
    具体解释VB中连接access数据库的几种方法
    C++中this指针的使用方法.
    秒杀多线程第四篇 一个经典的多线程同步问题
    设计模式学习03—抽象工厂模式
    Neutron中的Service类
    Opencv学习笔记(六)SURF学习笔记
  • 原文地址:https://www.cnblogs.com/AD-milk/p/12641242.html
Copyright © 2011-2022 走看看