都是迭代,为啥我一定要用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. web前端——美化效果总结

    概述 项目开发过程中使用到了不少web前端美化效果的方法,总结一下 1 图片作为背景 要实现的效果是,任意一张图片"img-page-background.png",不需要调整图片 ...

  2. vue 打包体积过大 实现懒加载 ????

    import Vue from ‘vue’ import Router from 'vue-router' //把路由对应的组件定义成异步组纪检 const hello = resolve => ...

  3. 一次 Druid 连接池泄露引发的血案!

    最近某个应用程序老是卡,需要重启才能解决问题,导致被各种投诉,排查问题是 Druid 连接池泄露引发的血案.. 异常日志如下: ERROR - com.alibaba.druid.pool.GetCo ...

  4. JavaScript实现集合与字典

    JavaScript实现集合与字典 一.集合结构 1.1.简介 集合比较常见的实现方式是哈希表,这里使用JavaScript的Object类进行封装. 集合通常是由一组无序的.不能重复的元素构成. 数 ...

  5. 【ERROR 1064 (42000)】MySQL中使用mysqladmin或set修改root密码时提示语法错误

    报错信息: mysql> mysqladmin -uroot -p123456 password 654321; ERROR 1064 (42000): You have an error in ...

  6. zabbix图表出现中文乱码

    搭建完成Zabbix监控服务器之后,切换到中文语言,图表展示出现乱码,如图所示 按照网上流传的上传windows下的字体的方法,还是不行,最后发现是PHP编译时的问题: php在编译时开启了-enab ...

  7. python 异步MySQL存库

    对于异步框架而言,这些延迟是无法接受的.因此, Twisted 提供了 twisted.enterprise.adbapi, 遵循DB-API 2.0协议的一个异步封装. adbapi 在单独的线程里 ...

  8. 当AI遇上K8S:使用Rancher安装机器学习必备工具JupyterHub

    Jupyter Notebook是用于科学数据分析的利器,JupyterHub可以在服务器环境下为多个用户托管Jupyter运行环境.本文将详细介绍如何使用Rancher安装JupyterHub来为数 ...

  9. Mol Cell Proteomics. | 用于鉴定新型融合转录本及其在癌细胞中的潜在翻译产物的多功能蛋白质组基因组学工具FusionPro

    期刊:Molecular & Cellular Proteomics 发表时间:June 17, 2019 DOI:10.1074/mcp.RA119.001456 分享人:任哲 内容与观点: ...

  10. VMware 虚拟机正在使用中

    1.出现报错信息: 2.找到安装目录下面的.lck后缀文件夹(如有多个则全部删除) 3.删除此文件夹 4.成功开启虚拟机