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真好用!
C# 便捷实现可迭代对象间的赋值的更多相关文章
- C++ 对象间的赋值与拷贝构造函数
1.对象间的赋值 /***A.h文件***/ #pragma once class A { public: int va; A(void); A(char* name); A(const A& ...
- 【Python】【容器 | 迭代对象 | 迭代器 | 生成器 | 生成器表达式 | 协程 | 期物 | 任务】
Python 的 asyncio 类似于 C++ 的 Boost.Asio. 所谓「异步 IO」,就是你发起一个 IO 操作,却不用等它结束,你可以继续做其他事情,当它结束时,你会得到通知. Asyn ...
- 孤荷凌寒自学python第十六天python的迭代对象
孤荷凌寒自学python第十六天python的迭代对象 (完整学习过程屏幕记录视频地址在文末,手写笔记在文末) 迭代也就是循环. python中的迭代对象有相关的如下几个术语: A容器 contrai ...
- 【ES6】迭代器与可迭代对象
ES6 新的数组方法.集合.for-of 循环.展开运算符(...)甚至异步编程都依赖于迭代器(Iterator )实现.本文会详解 ES6 的迭代器与生成器,并进一步挖掘可迭代对象的内部原理与使用方 ...
- NSNotification,NSNotificationCenter的使用、iOS中五种对象间传值的方式
学习内容 NSNitification与NotificationCenter(通知与通知中心) 通知的使用 [[NSNotificationCenter defaultCenter]addObserv ...
- Python迭代器,可迭代对象,生成器
迭代器 迭代器(iterator)有时又称游标(cursor)是程式设计的软件设计模式,可在容器物件(container,例如链表或阵列)上遍访的界面,设计人员无需关心容器物件的内存分配的实现细节. ...
- 使用AutoMapper进行对象间映射
在开发过程中,难免遇到下面这种情况:两个(或多个)对象所拥有的大多数属性是重复的,我们需要在对象间进行映射(即将一个对象的属性值赋给另一个对象.通常我们可以进行如下操作: A a=new A(); a ...
- Python中的可迭代对象与迭代器对象
刚刚学习Python,对“可迭代对象”和"迭代器对象"的个人理解,不知道对不对. 1.几个概念 (1)迭代工具:包括for循环.列表解析.in成员关系测试.....等等在内的,用于 ...
- Python生成器、迭代器、可迭代对象
把一个列表[]改成()就创建了一个生成器:generator,generator保存的是算法. 可以用于for循环的数据类型:1.集合类型:list tuple dict set str2.gener ...
随机推荐
- 全差分运算放大器ADA4930的分析(2)
前面解释了在ADA4930组成的单端转差分电路的输入电阻RIN的大小,可知当RF=RG=1KΩ的时候,RIN=1.33KΩ. 图1单端转差分电路 如图1所示,假设信号源为2V VPP的信号,信号源的内 ...
- JavaScript 工作原理之十三-CSS 和 JS 动画底层原理及如何优化其性能
原文请查阅这里,本文采用知识共享署名 4.0 国际许可协议共享,BY Troland. 本系列持续更新中,Github 地址请查阅这里. 这是 JavaScript 工作原理的第十三章. 概述 正如你 ...
- python初学者必看学习路线图!!!
python应该是近几年比较火的语言之一,很多人刚学python不知道该如何学习,尤其是没有编程基础想要从事程序员工作的小白,想必应该都会有此疑惑,包括我刚学python的时候也是通过从网上查找相关资 ...
- IntelliJ IDEA 2020 全家桶注册码
WU78YHTY7E-eyJsaWNlbnNlSWQiOiJPUVQzT0oyNVhFIiwibGljZW5zZWVOYW1lIjoi5rC45LmF5r+A5rS7IGlkZWEubWVkZW1pb ...
- Python中使用subprocess模块远程执行命令
使用subprocess模块执行远程命令 服务端代码 1 import socket 2 import subprocess 3 4 sh_server = socket.socket() 5 sh_ ...
- 网络编程---socket模块
内容中代码都是先写 server端, 再写 client端 1 TCP和UDP对比 TCP(Transmission Control Protocol)可靠的.面向连接的协议(eg:打电话).传输效 ...
- Microsoft Visual Studio 修改语言包
需求内容: 更改 Microsoft Visual Studio 界面的语言包(将中文改为英文) 解决方案: https://docs.microsoft.com/zh-cn/visualstudio ...
- vue 开发时候 nginx绑定多个系统 爆红 sockjs-node/info?t
如果你的浏览器,与NPM服务器,不是同一个机器(不是localhost),那么会导致这个报错. 我搜索了好久,才发现这个是可以在webpackjs里配置的(即vue.config.js): https ...
- android弱网络优化
1 网络请求,使用更好的网络请求方式 flutter有3种请求方式,flutter自带的io下httpclient请求,使用dart原生的http请求,dio请求. flutter还可以通过调用and ...
- Python基础篇_实例练习(二)
问题1:假设有同学A,A每周在工作日进步,周末退步,问一年(365天)后A同学是一年前的几倍? 工作日进步由用户输入,周末下降0.01即1% deyup = eval(input()) deyfact ...