十年网站开发经验 + 多家企业客户 + 靠谱的建站团队
量身定制 + 运营维护+专业推广+无忧售后,网站问题一站解决
对于String.Join(String, String[])这个方法,相信大家都有所了解。唯一不足的就是这个方法只能用于字符串数组,适用场景比较少。我所遇到的场景中,更多的是对List
实现的方式是对IEnumerable
成都创新互联公司专注于城步企业网站建设,响应式网站设计,商城建设。城步网站建设公司,为城步等地区提供建站服务。全流程定制网站开发,专业设计,全程项目跟踪,成都创新互联公司专业和态度为您提供的服务
///
/// 将数组合并成字符串,Action< ,TextWriter>
///
///
///
///
///
///
public static void Join(this IEnumerable enumerable,String separator,Action action,TextWriter output)
{
Func writeSp = (x, y) => { x.Write(y); return true; };
IEnumerator en = enumerable.GetEnumerator();
if(en.MoveNext())
{
do
{
action(en.Current,output);
} while(en.MoveNext() && writeSp(output, separator));
}
}
///
/// 将数组合并成字符串,Action< >
///
///
///
///
///
///
public static void Join(this IEnumerable enumerable,String separator,Action action,TextWriter output)
{
Func writeSp = (x, y) => { x.Write(y); return true; };
IEnumerator en = enumerable.GetEnumerator();
if(en.MoveNext())
{
do
{
action(en.Current);
} while(en.MoveNext() && writeSp(output, separator));
}
}
下面通过实现“DataTable转CSV”来对这两个方法和嵌套For循环进行对比。
在这个Demo里,DataTable有3列100行数据。对3种实现方式分别进行10000、100000和1000000循环。
Demo:
[TestMethod]
public void TestMethod5()
{
DataTable dt = new DataTable("1234");
dt.Columns.Add("A");
dt.Columns.Add("B");
dt.Columns.Add("C");
for(int i = 0; i < 100; i++)
{
dt.Rows.Add("A" + i, "B" + i, "C" + i);
}
StringBuilder sb;//= new StringBuilder();
StringWriter sw;// = new StringWriter(sb);
String rowSeparator = "\n";
String columnSeparator = ",";
//Console.WriteLine(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss:ffffff"));
DateTime time1 = DateTime.Now;
Int32 count = 1000000;
for(int c = 0; c < count; c++)
{
sb = new StringBuilder();
sw = new StringWriter(sb);
#region Action
// var columns = dt.Columns.OfType();
//// 写标题
//columns.Join(columnSeparator, (x) => x.ColumnName, sw);
//sw.Write(rowSeparator);
//// 写数据
//dt.Select().Join(rowSeparator, (x, x1) => columns.Join(columnSeparator, (y, y1) => { y1.Write('"'); y1.Write(x[y]); y1.Write('"'); }, x1), sw);
#endregion
#region Action
// var columns = dt.Columns.OfType();
//columns.Join(columnSeparator, (x) => sw.Write(x.ColumnName), sw);
//sw.Write(rowSeparator);
//dt.Select().Join(rowSeparator, (x) => columns.Join(columnSeparator, (y) => { sw.Write('"'); sw.Write(x[y]); sw.Write('"'); }, sw), sw);
#endregion
#region 嵌套for
Func func = (x, y) => { x.Write(y); return true; };
sb = new StringBuilder();
for(int i = 0; i < dt.Columns.Count && func(sw, columnSeparator); i++)
{
sw.Write(dt.Columns[i].ColumnName);
}
sw.Write(rowSeparator);
for(int i = 0; i < dt.Rows.Count && func(sw, rowSeparator); i++)
{
for(int j = 0; j < dt.Columns.Count && func(sw, columnSeparator); j++)
{
sw.Write('"');
sw.Write(dt.Rows[i][j]);
sw.Write('"');
}
}
#endregion
sw.Flush();
sw.Close();
//Console.WriteLine(sb.ToString());
}
//Console.WriteLine(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss:ffffff"));
DateTime time2 = DateTime.Now;
Console.WriteLine($"{time1.ToString("yyyy-MM-dd HH:mm:ss:ffffff")}\t{time2.ToString("yyyy-MM-dd HH:mm:ss:ffffff")}\t{time2.Ticks - time1.Ticks}");
}
测试结果:
类别 | 循环次数 | 开始时间 | 结束时间 | Ticks差 |
---|---|---|---|---|
Action |
10000 | 2018-11-05 22:13:58:619431 | 2018-11-05 22:14:01:708661 | 30862597 |
Action |
10000 | 2018-11-05 22:30:01:316414 | 2018-11-05 22:30:04:540565 | 32241503 |
嵌套for | 10000 | 2018-11-05 22:48:20:351136 | 2018-11-05 22:48:23:832171 | 34810345 |
Action |
100000 | 2018-11-05 22:17:45:756623 | 2018-11-05 22:18:14:361243 | 286046197 |
Action |
100000 | 2018-11-05 22:30:38:917299 | 2018-11-05 22:31:08:680268 | 297629687 |
嵌套for | 100000 | 2018-11-05 22:50:11:315021 | 2018-11-05 22:50:45:257604 | 339425834 |
Action |
1000000 | 2018-11-05 22:19:02:489665 | 2018-11-05 22:24:06:528472 | 3040388071 |
Action |
1000000 | 2018-11-05 22:32:09:871650 | 2018-11-05 22:37:05:125522 | 2952538718 |
嵌套for | 1000000 | 2018-11-05 22:51:18:319466 | 2018-11-05 22:56:46:534431 | 3282149643 |
从结果中可以看出,性能差距并不大。当然,由于嵌套For循环里使用索引来寻值,所以可能存在误差。
如果有错误或者更好的方法,欢迎指正。
题外话,方法命名为Join,可能与Linq的Join存在歧义,建议使用时换成其他名称。