想象一下我有
var points = new Point[]
{
new Point(1, 2),
new Point(2, 3)
};
要获得具有最小X的点,我可以:
var result = points.OrderBy(point => point.X).First();
但对于大型阵列,我认为这不是更快的选择。还有更快的选择吗?
答案 0 :(得分:3)
最好使用
int x = points.Min(p => p.X);
var result = points.First(p => p.X == x);
因为这消除了对该列表进行排序的必要性(即,O(n)
而不是O(n log n)
)。此外,它比使用OrderBy
和First
更清晰。
您甚至可以按如下方式编写扩展方法:
static class IEnumerableExtensions {
public static T SelectMin<T>(this IEnumerable<T> source, Func<T, int> selector) {
if (source == null) {
throw new ArgumentNullException("source");
}
int min = 0;
T returnValue = default(T);
bool flag = false;
foreach (T t in source) {
int value = selector(t);
if (flag) {
if (value < min) {
returnValue = t;
min = value;
}
}
else {
min = value;
returnValue = t;
flag = true;
}
}
if (!flag) {
throw new InvalidOperationException("source is empty");
}
return returnValue;
}
用法:
IEnumerable<Point> points;
Point minPoint = points.SelectMin(p => p.X);
您可以根据自己的需要进行推广。这样做的好处是可以避免潜在地走两次列表。
答案 1 :(得分:2)
以下应该是最快的,但不是最漂亮的方式:
public static T MinValue<T>(this IEnumerable<T> e, Func<T, int> f)
{
if (e == null) throw new ArgumentException();
var en = e.GetEnumerator();
if (!en.MoveNext()) throw new ArgumentException();
int min = f(en.Current);
T minValue = en.Current;
int possible = int.MinValue;
while (en.MoveNext())
{
possible = f(en.Current);
if (min > possible)
{
min = possible;
minValue = en.Current;
}
}
return minValue;
}
我只包含了int扩展名,但是做其他人也很简单。
编辑:根据Jason修改。
答案 2 :(得分:0)
对于今天希望这样做的人来说,MoreLinq是NuGet提供的库,其中包括其他答案提供的运算符以及框架中没有的其他一些有用的操作。