我正在为C#中的AI比赛写一个条目,我正在寻找一种更优雅的方式来搜索项目。 (我对嵌入式C编程更熟悉,但我更喜欢C#进行人工智能竞赛。)
比赛服务器使用dmcs编译条目,即.Net framework 4.0;我使用Visual Studio Express 2013进行测试。
我尝试搜索列表中的项目,其中参数的最大值也符合某个先决条件。但是,我不想要最大值,我想要具有最大值的项目。
这是我使用foreach循环执行我想要的原始代码:
List<Region> myList = new List<Region>();
// ...
// myList gets populated with elements
// ...
Region biggest = null;
int biggestSize = -1;
foreach (Region r in myList)
{
// We only want elements that are eligible for expansion
if (r.EligibleForExpansion())
{
if (r.Size > biggestSize)
{
biggest = r;
biggestSize = r.Size;
}
}
}
return biggest; // I want the biggest Region, not the Size of the biggest region.
我试图找到一种更优雅的方式来做到这一点,所以我的代码中没有foreach循环。我试过这个:
return myList.Max(delegate(Region r) { if (r.EligibleForExpansion()) return r.Size; else return -1; });
然而,它返回最大区域的Size值,而不是最大的Region本身(这就是我需要的)。
我知道如果没有Region满足要求,我的foreach代码将返回null,而Max代码将给-1(或任何不满足要求的Region);我可以处理任何一种方式。
我不认为我可以让Region IC比较;我有很多区域对象的搜索,我需要在不同的时间按不同的参数排序,因此比较函数在不同的搜索中会有所不同。
我可以将我的foreach代码包装在一个静态函数中,并在我需要搜索的地方调用它,但似乎应该有更优雅的方法在C#中执行此操作。
答案 0 :(得分:4)
使用MaxBy
from moreLINQ library:
public static TSource MaxBy<TSource, TKey>(this IEnumerable<TSource> source,
Func<TSource, TKey> selector)
{
return source.MaxBy(selector, Comparer<TKey>.Default);
}
public static TSource MaxBy<TSource, TKey>(this IEnumerable<TSource> source,
Func<TSource, TKey> selector, IComparer<TKey> comparer)
{
if (source == null) throw new ArgumentNullException("source");
if (selector == null) throw new ArgumentNullException("selector");
if (comparer == null) throw new ArgumentNullException("comparer");
using (var sourceIterator = source.GetEnumerator())
{
if (!sourceIterator.MoveNext())
{
throw new InvalidOperationException("Sequence contains no elements");
}
var max = sourceIterator.Current;
var maxKey = selector(max);
while (sourceIterator.MoveNext())
{
var candidate = sourceIterator.Current;
var candidateProjected = selector(candidate);
if (comparer.Compare(candidateProjected, maxKey) > 0)
{
max = candidate;
maxKey = candidateProjected;
}
}
return max;
}
}
像那样:
var item = myList.Where(x => x.EligibleForExpansion())
.MaxBy(x => x.Size);
答案 1 :(得分:2)
这个怎么样?
myList.Where(r => r.EligibleForExpansion).OrderBy(r => r.Size).LastOrDefault()
答案 2 :(得分:1)
您可以使用Aggregate
开箱即用:
var item = myList
.Where(r => r.EligibleForExpansion())
.Aggregate((Region)null, (max, cur) => (max == null ? cur : cur.Size > max.Size ? cur : max));
如果Region
是一个值类型(它不是),你可以将初始值包装在一个可空的值中,并为空列表获取一个空值:
var item = myList
.Where(r => r.EligibleForExpansion())
.Aggregate((Region?)null, (max, cur) => (max == null ? cur : cur.Size > max.Value.Size ? cur : max));