我想我也很习惯使用LINQ,但这很慢,我确实使用了探查器,它消耗了我尝试执行的时间的65%
var unlock = Locked.OrderBy(x => x.Weight) //double
.ThenByDescending(x => x.Stuff?.Level ?? 100) //int
.ThenBy(x => x.Penalty) //double
.FirstOrDefault();
Locked是一个列表,我知道排序会更改列表,但是我并不在乎,我只是想使其工作(如果可能),下面的代码不会提供与上面的LINQ相同的结果;
Locked.Sort(delegate (Node a, Node b)
{
int xdiff = a.Weight.CompareTo(b.Weight);
if (xdiff != 0) return xdiff;
var aStuff = a.Stuff?.Level ?? 100;
var bStuff = b.Stuff?.Level ?? 100;
xdiff = -1 * aStuff.CompareTo(bStuff);
if (xdiff != 0) return xdiff;
return xdiff = a.Penalty.CompareTo(b.Penalty);
});
var unlock = Locked[0];
第一件事是,可以使用List.Sort进行 complex 排序吗?升序/先降序/再升序?
如果是,我的错误在哪里?
接下来是,有没有一种更快的方式来做我想做的事情?
答案 0 :(得分:9)
如果您紧跟在“第一或默认”(最小/最大)之后,则无需排序-您可以通过一次O(N)传递来进行此操作。选择第一项并将其存储在变量中;现在依次遍历所有 other 项:如果根据您的标准更可取:将其放入变量中。当您走到尽头时,您就有了赢家。
答案 1 :(得分:2)
您可以创建一个自定义比较器:
var comparer = Comparer<SomeItem>.Create((a, b) =>
a.A == a.B
? a.B == b.B
? a.C == b.C
? 0
: b.C - a.C //the order of these subtractions will affect the order
: a.B - b.B
: a.A - b.A);
然后使用morelinq的MinBy
:
IEnumerable<SomeItem> items = ...;
var best = items.MinBy(x => x, comparer); //.First() if it's morelinq3
...或者如果创建比较器看起来很吓人,我写了ComparerBuilder library来简化它:
var builder = new ComparerBuilder<Item>();
var comparer = builder
.SortKey(x => x.A)
.ThenKeyDescending(x => x.B)
.ThenKey(x => x.C)
.Build();
var selectedItem = items.MinBy(x => x, comparer).First();
答案 2 :(得分:0)
基于Mark的答案,我想到了这一点;
Node unlock = null;
Node locked = null;
if (Locked.Count > 0)
{
unlock = Locked[0];
for (var i = 1; i < Locked.Count; ++i)
{
locked = Locked[i];
if (unlock.Weight > locked.Weight)
{
unlock = locked;
}
else if (unlock.Weight == locked.Weight)
{
var unlockStuffLevel = unlock.Stuff?.Level ?? 100;
var lockedStuffLevel = locked.Stuff?.Level ?? 100;
if (unlockStuffLevel < lockedStuffLevel)
{
unlock = locked;
}
else if (unlockStuffLevel == lockedStuffLevel )
{
if (unlock.Penalty > locked.Penalty)
{
unlock = locked;
}
}
}
}
}
分析表明,这现在需要大约15%的时间,而不是之前的65%,这似乎可以复制与LINQ相同的结果,我可能会在以后进行进一步的优化,但现在我有了想要的东西