以指定分隔符串联字符串-创新互联

对于String.Join(String, String[])这个方法,相信大家都有所了解。唯一不足的就是这个方法只能用于字符串数组,适用场景比较少。我所遇到的场景中,更多的是对List中的某属性进行串联。尚未发现已实现该功能的方法,于是自己实现了该功能。
实现的方式是对IEnumerable进行扩展。

创新互联是一家专注网站建设、网络营销策划、成都小程序开发、电子商务建设、网络推广、移动互联开发、研究、服务为一体的技术型公司。公司成立10多年以来,已经为超过千家葡萄架各业的企业公司提供互联网服务。现在,服务的超过千家客户与我们一路同行,见证我们的成长;未来,我们一起分享成功的喜悦。
/// 
        /// 将数组合并成字符串,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差
Action100002018-11-05 22:13:58:6194312018-11-05 22:14:01:70866130862597
Action100002018-11-05 22:30:01:3164142018-11-05 22:30:04:54056532241503
嵌套for100002018-11-05 22:48:20:3511362018-11-05 22:48:23:83217134810345
Action1000002018-11-05 22:17:45:7566232018-11-05 22:18:14:361243286046197
Action1000002018-11-05 22:30:38:9172992018-11-05 22:31:08:680268297629687
嵌套for1000002018-11-05 22:50:11:3150212018-11-05 22:50:45:257604339425834
Action10000002018-11-05 22:19:02:4896652018-11-05 22:24:06:5284723040388071
Action10000002018-11-05 22:32:09:8716502018-11-05 22:37:05:1255222952538718
嵌套for10000002018-11-05 22:51:18:3194662018-11-05 22:56:46:5344313282149643

从结果中可以看出,性能差距并不大。当然,由于嵌套For循环里使用索引来寻值,所以可能存在误差。
如果有错误或者更好的方法,欢迎指正。
题外话,方法命名为Join,可能与Linq的Join存在歧义,建议使用时换成其他名称。

另外有需要云服务器可以了解下创新互联scvps.cn,海内外云服务器15元起步,三天无理由+7*72小时售后在线,公司持有idc许可证,提供“云服务器、裸金属服务器、高防服务器、香港服务器、美国服务器、虚拟主机、免备案服务器”等云主机租用服务以及企业上云的综合解决方案,具有“安全稳定、简单易用、服务可用性高、性价比高”等特点与优势,专为企业上云打造定制,能够满足用户丰富、多元化的应用场景需求。


网页名称:以指定分隔符串联字符串-创新互联
文章网址:http://hbruida.cn/article/eshge.html