我正在寻找一种将大型int []转换为csv字符串的字符串[]的有效方法,其中每个csv限制为最多4000个字符。数组中的值可以是1和int.MaxValue之间的任何值。
这是我的最终代码:
public static string[] GetCSVsFromArray(int[] array, int csvLimit)
{
List<string> parts = new List<string>();
StringBuilder sb = new StringBuilder();
foreach(int id in array)
{
string intId = id.ToString();
if (sb.Length + intId.Length < csvLimit)
sb.Append(intId).Append(",");
else
{
if (sb.Length > 0)
sb.Length--;
parts.Add(sb.ToString());
sb.Length = 0;
}
}
if(sb.Length>0)
parts.Add(sb.ToString());
return parts.ToArray();
}
有更有效的方法吗?
所以这就是我现在正在使用的(我能够将返回参数更改为List类型以在末尾保存ToArray()调用):
public static List<string> GetCSVsFromArray(int[] array, int csvLimit)
{
List<string> parts = new List<string>();
StringBuilder sb = new StringBuilder();
foreach(int id in array)
{
string intId = id.ToString();
if (sb.Length + intId.Length < csvLimit)
sb.Append(intId).Append(",");
else
{
if (sb.Length > 0)
sb.Length--;
parts.Add(sb.ToString());
sb.Length = 0;
}
}
if(sb.Length>0)
parts.Add(sb.ToString());
return parts;
}
表现结果:
10,000,000项csv限制为4000个字符
虽然我在开发人员计算机上只保存了4ms删除ToArray()调用,但这似乎在速度慢得多的机器上有显着差异(在DELL D620上保存超过200ms)
答案 0 :(得分:2)
为每个数字创建一个新字符串时,您正在进行大量的堆内存分配,只是为了计算位数。使用following method计算数字中的位数(请参阅下面的方法)。
所以而不是
string intId = id.ToString();
if (sb.Length + intId.Length < csvLimit)
只需使用:
if (sb.Length + this.GetIntegerDigitCount(id) < csvLimit)
<强>结果:强>
编辑:有关大型csv限制的更多结果
产品:千万; csvLimit:4000;旧:2091ms,新:1868ms,差异:223ms 更快= 111.937901498929%
代码I用于衡量时间:
double elapsedOld = 0;
double elapsedNew = 0;
int count = 10000000;
int csvLimit = 4000;
var items = Enumerable.Range(0, count).ToArray();
var watch = Stopwatch.StartNew();
this.GetCsVsFromArray(items, csvLimit);
watch.Stop();
elapsedOld = watch.ElapsedMilliseconds;
watch = Stopwatch.StartNew();
this.GetCsVsFromArrayTuned(items, csvLimit);
watch.Stop();
elapsedNew = watch.ElapsedMilliseconds;
var stat = String.Format(
"Items:{0}; csvLimit:{1}; Old:{2}ms, New:{3}ms, Diff:{4}ms faster = {5}%",
count,
csvLimit,
elapsedOld,
elapsedNew,
elapsedOld - elapsedNew,
elapsedOld * 100 / elapsedNew);
<强> GetIntegerDigitCount 强>:
public int GetIntegerDigitCount(int valueInt)
{
double value = valueInt;
int sign = 0;
if (value < 0)
{
value = -value;
sign = 1;
}
if (value <= 9)
{
return sign + 1;
}
if (value <= 99)
{
return sign + 2;
}
if (value <= 999)
{
return sign + 3;
}
if (value <= 9999)
{
return sign + 4;
}
if (value <= 99999)
{
return sign + 5;
}
if (value <= 999999)
{
return sign + 6;
}
if (value <= 9999999)
{
return sign + 7;
}
if (value <= 99999999)
{
return sign + 8;
}
if (value <= 999999999)
{
return sign + 9;
}
return sign + 10;
}
答案 1 :(得分:1)
Linq在这里可以加速一些事情。经过一些修改后,您的代码将看起来像这样:
public static string[] GetCSVsFromArray(int[] array, int csvLimit)
{
List<string> parts = new List<string>();
StringBuilder sb = new StringBuilder();
foreach (string intId in array.Select(id => id.ToString()))
{
if (sb.Length + intId.Length < csvLimit)
sb.Append(intId).Append(",");
else
{
if (sb.Length > 0)
sb.Length--; parts.Add(sb.ToString()); sb.Length = 0;
}
}
return parts.ToArray();
}
答案 2 :(得分:0)
using System.Linq;
public static string[] GetCSVsFromArray(int[] array, int limit)
{
int i = 0;
return array.Select(a => a.ToString())
.GroupBy(a => { i += a.Length; return (i - a.Length) / limit; })
.Select(a => string.Join(",",a))
.ToArray();
}