2009-10-15 2 views

답변

3

이 문제는이 목록을 정렬의 필요성을 제거로

int x = points.Min(p => p.X); 
var result = points.First(p => p.X == x); 

를 사용하는 것이 더 좋습니다 (즉, 그것은 반대로 O(n)되는, 말, O(n log n)). 또한 OrderByFirst을 사용하는 것보다 명확합니다.

다음과 같이 더욱 확장 메서드를 작성할 수

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); 

당신은 여러분의 필요에 일반화 할 수 있습니다. 이것의 장점은 잠재적으로 목록을 두 번 걷는 것을 피할 수 있다는 것입니다.

+0

내 논리가 실패하지 않는 한 .Min()은 모든 요소를 ​​검사해야합니까? 그런 다음 그 값을 반환합니다. 먼저 X 값이있는 첫 번째 점을 찾을 때까지 동일한 목록을 다시 시작합니다. 최악의 경우는 2 * n입니까? –

+0

이 문제를 해결하기위한 확장 방법을 추가했습니다. 둘째,'2 * n'은'O (n)'입니다. – jason

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

코멘트 :'Count'는 (IEnumerable에) 절대적으로 필요한 경우가 아니라면 호출하는 것이 좋지 않습니다. 'IEnumerable'을 통해 걷는 것이 값 비싸면, 이것은 나쁘다. – jason

+0

또 다른 설명 :'while' 루프에서 현재 요소에서'f (en.Current)'를 두 번 계산합니다. 'f'가 비싸다면 이것은 최적이 아닙니다. – jason

0

MoreLinq은 오늘 NuGet에서 제공하는 라이브러리로 다른 답변과 프레임 워크에없는 유용한 작업을 제공합니다.

관련 문제