问题:下面的代码可以处理较小的数据集,但是对于较大的数量,它是不可行的.目前,我们正在运行它,它需要超过50分钟(和计数).我们可以做些什么来减少将更大的数据集运行到可承受的水平所需的时间?
感谢您的时间.手指交叉.
// The buyList contains about 93,000 objects. public voID CreateUniqueBuyList(List<EveObjModel> buyList) { List<EveObjModel> uniqueBuyList = new List<EveObjModel>(); foreach (EveObjModel obj in buyList) { int duplicateCount = 0; for (int i = 0; i < uniqueBuyList.Count; i++) { if (uniqueBuyList[i].type_ID == obj.type_ID) duplicateCount++; } if (duplicateCount == 1) { foreach (EveObjModel objinUnique in uniqueBuyList) { if (obj.type_ID == objinUnique.type_ID && obj.price > objinUnique.price) { // instead of adding obj,the price is just changed to the price in the obj. objinUnique.price = obj.price; } else if (obj.type_ID == objinUnique.type_ID && obj.price == objinUnique.price) { //uniqueBuyList.RemoveAll(item => item.type_ID == obj.type_ID); } else { // Hitting this mean that there are other objects with same type and higher price OR its not the same type_ID } } } else if (duplicateCount > 1) { // shud not happn... } else { uniqueBuyList.Add(obj); } continue; } foreach (EveObjModel item in uniqueBuyList.OrderBy(item => item.type_ID)) { buyListtextFIEld.Text += $"Eve Online Item! Type-ID is: {item.type_ID},Price is {item.price}\n"; } }
这是我们的EveObjModel类
using System; using System.Collections.Generic; using System.linq; using System.Runtime.Serialization; using System.Text; using System.Threading.Tasks; namespace EveOnlineApp { [DataContract] public class EveObjModel { [DataMember] public bool is_buy_order { get; set; } [DataMember] public double price { get; set; } [DataMember] public int type_ID { get; set; } }}解决方法 这个过程很慢并不奇怪,因为您使用的算法(使用嵌套循环)至少具有二次O(N * N)时间复杂度,这种数据集的大小非常慢.
一种方法是使用liNQ GroupBy运算符,它在内部使用基于散列的查找,因此理论上具有O(N)时间复杂度.因此,您按type_ID进行分组,对于每个组(具有相同键的元素列表),请使用最大价格的一个:
var uniqueBuyList = buyList .GroupBy(e => e.type_ID) .Select(g => g.OrderByDescending(e => e.price).First()) .ToList();
对于cource,您不需要对列表进行排序以获取具有最大价格的元素.更好的版本是使用Aggregate方法(基本上是foreach循环):
var uniqueBuyList = buyList .GroupBy(e => e.type_ID) .Select(g => g.Aggregate((e1,e2) => e1.price > e2.price ? e1 : e2)) .ToList();
另一种非基于liNQ的方法是通过type_ID升序,降价来对输入列表进行排序.然后在排序列表上执行一个循环并获取每个type_ID组的第一个元素(它将具有最大价格):
var comparer = Comparer<EveObjModel>.Create((e1,e2) =>{ int result = e1.type_ID.Compareto(e2.type_ID); if (result == 0) // e1.type_ID == e2.type_ID result = e2.price.Compareto(e1.price); // e1,e2 exchanged to get descending order return result;});buyList.sort(comparer);var uniqueBuyList = new List<EveObjModel>();EveObjModel last = null;foreach (var item in buyList){ if (last == null || last.type_ID != item.type_ID) uniqueBuyList.Add(item); last = item;}
这种算法的复杂性是O(N * log(N)),因此它比基于散列的算法更差(但比原始算法要好得多).好处是它使用更少的内存,结果列表已经按type_ID排序,因此您不需要使用OrderBy.
总结以上是内存溢出为你收集整理的c# – 如何最大限度地减少大数据集的运行时间(从93,773个对象列表中创建唯一对象列表)全部内容,希望文章能够帮你解决c# – 如何最大限度地减少大数据集的运行时间(从93,773个对象列表中创建唯一对象列表)所遇到的程序开发问题。
如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)