c# – 如何提高这个算法的性能?
我有一个文本文件与100000对:字和频率.
test.in文件与文字: > 1行 – 所有字频对的总计数 我解析这个文件并把这些单词放进去 Dictionary<string,double> dictionary; 我想在以下代码中执行一些搜索顺序逻辑: for(int i=0;i<15000;i++) { tempInputWord = //take data from file(or other sources) var adviceWords = dictionary .Where(p => p.Key.StartsWith(searchWord,StringComparison.Ordinal)) .OrderByDescending(ks => ks.Value) .ThenBy(ks => ks.Key,StringComparer.Ordinal) .Take(10) .ToList(); //some output } 问题:该代码必须在不到10秒的时间内运行. 在我的电脑(核心i5 2400,8gb RAM)与Parallel.For() – 约91秒. 你能给我一些如何提高性能的建议吗? 更新: 万岁!我们做到了! 最后的代码: var kvList = dictionary.OrderBy(ks => ks.Key,StringComparer.Ordinal).ToList(); var strComparer = new MyStringComparer(); var intComparer = new MyIntComparer(); var kvListSize = kvList.Count; var allUserWords = new List<string>(); for (int i = 0; i < userWordQuantity; i++) { var searchWord = Console.ReadLine(); allUserWords.Add(searchWord); } var result = allUserWords .AsParallel() .AsOrdered() .Select(searchWord => { int startIndex = kvList.BinarySearch(new KeyValuePair<string,int>(searchWord,0),strComparer); if (startIndex < 0) startIndex = ~startIndex; var matches = new List<KeyValuePair<string,int>>(); bool isNotEnd = true; for (int j = startIndex; j < kvListSize ; j++) { isNotEnd = kvList[j].Key.StartsWith(searchWord,StringComparison.Ordinal); if (isNotEnd) matches.Add(kvList[j]); else break; } matches.Sort(intComparer); var res = matches.Select(s => s.Key).Take(10).ToList(); return res; }); foreach (var adviceWords in result) { foreach (var adviceWord in adviceWords) { Console.WriteLine(adviceWord); } Console.WriteLine(); }
解决方法
>按键排序列表< KeyValuePair< string,decimal>>替换字典.
对于搜索,我使用一个子字符串直接在其前缀之前进行序数比较.所以我可以用二进制搜索找到第一个候选人.由于候选人是连续的,我可以用TakeWhile代替Where. int startIndex = dictionary.BinarySearch(searchWord,comparer); if(startIndex < 0) startIndex = ~startIndex; var adviceWords = dictionary .Skip(startIndex) .TakeWhile(p => p.Key.StartsWith(searchWord,StringComparison.Ordinal)) .OrderByDescending(ks => ks.Value) .ThenBy(ks => ks.Key) .Select(s => s.Key) .Take(10).ToList(); >确保对所有操作使用顺序比较,包括初始排序,二进制搜索和StartsWith检查.>我会在并行循环之外调用Console.ReadLine.可能使用AsParallel().在搜索单词的集合上选择(…)而不是Parallel.For. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |