我有一个字符串类型,它将以
格式返回数千条记录 key1,val1,val2,val3,val4,val5:key2,val6,val7,val8,val9,val10:key3,val11,val12,val13,val14,val15
我想将它作为Key,List分配给字典,所以它看起来像
KEY1,[VAL1,VAL2,VAL3,VAL4,val5]
KEY2,[VAL6,val7,的Val8,val9,val10]
KEY3,[VAl11难,val12,val13,val14,val15]
。 。
所有键在字符串中都是唯一的,列表大小对于所有记录都是常量。
目前我正在使用Split并使用
循环每条记录 //short example string - may contain 1000's
string newstr = @"key1,val1,val2,val3,val4,val5:key2,val6,val7,val8,val9,val10:key3,val11,val12,val13,val14,val15";
Dictionary<string, List<string>> mydictionary = new Dictionary<string, List<string>>();
foreach (string item in newstr.Split(':'))
{
List<string> list = new List<string>(item.Split(','));
mydictionary.Add(list[0], list);
}
我的问题是,对于使用C#4.0而不是循环的1000个记录,是否有更高效/更快的方法?
更新:测试了以下各种答案的“正确”时间
static void Main(string[] args)
{
System.IO.StreamReader myFile = new System.IO.StreamReader(@"C:\Users\ooo\Desktop\temp.txt");
string newstr = myFile.ReadToEnd();
myFile.Close();
TimeSpan ts;
TimeSpan te;
Stopwatch stopWatch = new Stopwatch();
stopWatch.Start();
ts = stopWatch.Elapsed;
Dictionary<string, List<string>> mydictionary = new Dictionary<string, List<string>>();
foreach (string item in newstr.Split(':'))
{
List<string> list = new List<string>(item.Split(','));
mydictionary.Add(list[0], list);
}
te = stopWatch.Elapsed;
Console.WriteLine("MyTime: " + (te - ts).ToString());
ts = stopWatch.Elapsed;
var result = newstr.Split(':')
.Select(line => line.Split(','))
.ToDictionary(bits => bits[0],
bits => bits.Skip(1).ToList());
te = stopWatch.Elapsed;
Console.WriteLine("JonSkeet: " + (te - ts).ToString());
ts = stopWatch.Elapsed;
string[] keysAndValues = newstr.Split(':');
var newdictionary = new Dictionary<string, List<string>>(keysAndValues.Length);
foreach (string item in keysAndValues)
{
List<string> list = new List<string>(item.Split(','));
newdictionary.Add(list[0], list);
}
te = stopWatch.Elapsed;
Console.WriteLine("Joe: " + (te - ts).ToString());
Console.WriteLine("Records: " + mydictionary.Count.ToString());
stopWatch.Stop();
}
答案 0 :(得分:3)
以下内容可能更快,因为构建的Dictionary具有避免重新分配所需的容量:
//short example string - may contain 1000's
string newstr = ...;
string[] keysAndValues = newstr.Split(':');
var mydictionary = new Dictionary<string, List<string>>(keysAndValues.Length);
foreach (string item in keysAndValues)
{
List<string> list = new List<string>(item.Split(','));
mydictionary.Add(list[0], list);
// remove key from list to match Jon Skeet's implementation
list.RemoveAt(0);
}
比Jon Skeet的LINQ版本更不易读。
答案 1 :(得分:2)
听起来你想要这样的东西:
var result = text.Split(':')
.Select(line => line.Split(','))
.ToDictionary(bits => bits[0],
bits => bits.Skip(1).ToList());
它可能不再是高效,当然......你有没有测量到它需要?如果你只为“成千上万”的记录做这个,我希望它能在眨眼之间完成。此外,我希望在此代码出现之前,任何IO(网络,磁盘)都是瓶颈。
来自你的评论:
它实际上非常快而且不是瓶颈,但如果有更快的替代方案,我总是尽量避免循环
不要那样做。瞄准执行该作业的最简单的代码,然后检查它是否执行足够。我个人更喜欢我的基于LINQ的代码,但你现有的代码也很好。任何更快的替代方案很可能最终难以编写,读取和维护。如果收益微不足道,你为什么要去努力?
请注意,我的代码不将密钥作为列表中的第一个值 - 它与规范匹配,但不符合示例代码。
答案 2 :(得分:2)
根据LINQ解决方案(如@ JonSkeet)运行您发布的代码,表明LINQ大约是当前方法为超过1000条记录所用的时间的两倍。
因此,回答你的问题:
对于使用C#4.0而不是循环的1000个记录,有更高效/更快的方法吗?
我会说不。
基准测试代码:
var value = "key{0},val1,val2,val3,val4,val5:";
string newstr = "";
for (int i = 0; i <= 1000; i++)
{
newstr += String.Format(value, i + 1);
}
var sw = new System.Diagnostics.Stopwatch();
sw.Start();
Dictionary<string, List<string>> mydictionary = new Dictionary<string, List<string>>();
foreach (string item in newstr.Split(':'))
{
List<string> list = new List<string>(item.Split(','));
mydictionary.Add(list[0], list);
}
sw.Stop();
Console.WriteLine("Looping time: " + sw.Elapsed.ToString());
sw.Reset();
sw.Start();
var result = newstr.Split(':')
.Select(line => line.Split(','))
.ToDictionary(bits => bits[0],
bits => bits.Skip(1).ToList());
sw.Stop();
Console.WriteLine("LINQ time: " + sw.Elapsed.ToString());
Console.ReadKey();