都是迭代,为啥我一定要用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真好用!

C# 便捷实现可迭代对象间的赋值的更多相关文章

  1. C++ 对象间的赋值与拷贝构造函数

    1.对象间的赋值 /***A.h文件***/ #pragma once class A { public: int va; A(void); A(char* name); A(const A& ...

  2. 【Python】【容器 | 迭代对象 | 迭代器 | 生成器 | 生成器表达式 | 协程 | 期物 | 任务】

    Python 的 asyncio 类似于 C++ 的 Boost.Asio. 所谓「异步 IO」,就是你发起一个 IO 操作,却不用等它结束,你可以继续做其他事情,当它结束时,你会得到通知. Asyn ...

  3. 孤荷凌寒自学python第十六天python的迭代对象

    孤荷凌寒自学python第十六天python的迭代对象 (完整学习过程屏幕记录视频地址在文末,手写笔记在文末) 迭代也就是循环. python中的迭代对象有相关的如下几个术语: A容器 contrai ...

  4. 【ES6】迭代器与可迭代对象

    ES6 新的数组方法.集合.for-of 循环.展开运算符(...)甚至异步编程都依赖于迭代器(Iterator )实现.本文会详解 ES6 的迭代器与生成器,并进一步挖掘可迭代对象的内部原理与使用方 ...

  5. NSNotification,NSNotificationCenter的使用、iOS中五种对象间传值的方式

    学习内容 NSNitification与NotificationCenter(通知与通知中心) 通知的使用 [[NSNotificationCenter defaultCenter]addObserv ...

  6. Python迭代器,可迭代对象,生成器

    迭代器 迭代器(iterator)有时又称游标(cursor)是程式设计的软件设计模式,可在容器物件(container,例如链表或阵列)上遍访的界面,设计人员无需关心容器物件的内存分配的实现细节. ...

  7. 使用AutoMapper进行对象间映射

    在开发过程中,难免遇到下面这种情况:两个(或多个)对象所拥有的大多数属性是重复的,我们需要在对象间进行映射(即将一个对象的属性值赋给另一个对象.通常我们可以进行如下操作: A a=new A(); a ...

  8. Python中的可迭代对象与迭代器对象

    刚刚学习Python,对“可迭代对象”和"迭代器对象"的个人理解,不知道对不对. 1.几个概念 (1)迭代工具:包括for循环.列表解析.in成员关系测试.....等等在内的,用于 ...

  9. Python生成器、迭代器、可迭代对象

    把一个列表[]改成()就创建了一个生成器:generator,generator保存的是算法. 可以用于for循环的数据类型:1.集合类型:list tuple dict set str2.gener ...

随机推荐

  1. vue学习笔记(四)

    一.vue-router 1.简介 我们经常使用vue开发单页面应用程序(SPA).在开发SPA过程中,路由是必不可少的部分,vue的官方推荐是vue-router.单页面应用程序看起来好像是一个页面 ...

  2. 课题:html5图像羽化(不规则区域羽化,feather,html5羽化)

    下午搜索了一堆相关文章,没有找到符合要求的. 对一张图片应用不规则区域的羽化,该怎么做呢? 首先去查了下 羽化的原理,然而没有什么用, 然后就开始从表现层去研究怎么模拟? idea 1: blur滤镜 ...

  3. C++泛化双向链表

    泛型双向链表 双向链表(doublyLinkedList.h) /******************************************************************* ...

  4. C++对拍

    作为一名OIer,比赛时,对拍是必须的 不对拍,有时可以悔恨终身 首先,对拍的程序 一个是要交的程序 另一个可以是暴力.搜索等,可以比较慢,但是必须正确 下面是C++版对拍程序(C++ & c ...

  5. 复习笔记——1. C语言基础知识回顾

    1. 数据类型 1.1 基本数据类型 整型:int, long,unsigned int,unsigned long,long long-- 字符型:char 浮点型:float, double-- ...

  6. iview 踩坑之旅

    公司重构管理系统,框架定了vue,UI在element和iview之间选,element样式被吐槽丑,于是选了iview,但是,,这个坑多啊... 废话少说,罗列了iview中容易出错或者懵逼的一些地 ...

  7. c:\Windows\system32\rundll32.exe Windows无法访问指定设备、路径或文件,你可能没有适当的权限访问该项目

    非常懂如何修改权限的可以尝试,否则老老实实地重新注册的系统的.dll文件 重新注册方法如下: WIN+R下输入命令: cmd /c for %i in (%windir%\system32\*.dll ...

  8. python学习-练习题兔子生长问题巩固

    有一对兔子,一个月之后成熟,成熟之后每个月会生出一对兔子,理想状态下兔子不会死,请问n个月后有多少兔子? 分析:第一个月:1 第二个月:1 第三个月:2 第四个月:3 第五个月:5 第六个月:8 从前 ...

  9. Spring Cloud 理论篇

    show me the code and talk to me,做的出来更要说的明白 github同步收录 我是布尔bl,你的支持是我分享的动力! 微服务 在 jsp 时代,应用前后端耦合,前后端 a ...

  10. Ubuntu16.04 desktop 设置共享文件夹 -- 图形界面配置

    1. 安装 安装samba 直接采用 Ubuntu16.04 desktop 里面的安装向导来完成: 选中需要共享的文件夹 -> 右键 “local Network Share” -> 安 ...