2011-07-01 3 views
7

각 반복에서 테스트하지 않고 첫 번째 IEnumerable 항목을 다른 IEnumerable 항목과 다르게 처리하는 가장 우아한 방법은 무엇입니까? 각 반복에 대한 테스트와첫 번째 IEnumerable 항목을 다르게 처리하는 가장 우아한 방법

, 그 결과는 다음과 같습니다

// "first item done" flag 
bool firstDone = false; 

// items is an IEnumerable<something> 
foreach (var item in items) 
{ 
    if (!firstDone) 
    { 
     // do this only once 
     ProcessDifferently(item); 
     firstDone = true; 
     continue; 
    } 

    ProcessNormally(item); 
} 

을 내가 할 경우이 : 그것은 내가 피하고자하는, 두 번 GetEnumerator를 호출합니다

ProcessDifferently(items.First()); 
ProcessNormally(items.Skip(1)); // this calls `items.GetEnumerator` again 

(대한 예를 들어 Linq-to-SQL의 경우).

코드를 여러 번 수행해야한다면 어떻게할까요?

public void Process<T>(IEnumerable<T> source, 
         Action<T> firstAction, 
         Action<T> remainderAction) 
{ 
    // TODO: Argument validation 
    using (var iterator = source.GetEnumerator()) 
    { 
     if (iterator.MoveNext()) 
     { 
      firstAction(iterator.Current); 
     } 
     while (iterator.MoveNext()) 
     { 
      remainderAction(iterator.Current); 
     } 
    } 
} 

로 호출 : 나는 여러 장소에서 그것을 할 필요가있는 경우

답변

12

, 나는 방법을 추출하는 것

Process(items, ProcessDifferently, ProcessNormally); 

다른 옵션도 있습니다,하지만 정말에 따라 달라집니다 그 상황.

+0

감사합니다. 깨끗하고 깨끗합니다. 정확히 내가 뭘 물었 을까. – dilbert

0

당신은 그것을 구식 방법을 수행 할 수 있습니다

var itemsList = items.ToList(); 
ProcessDifferently(itemsList[0]); 

for(int i=1;i<itemsList.Count;i++) 
{ 
    ProcessNormally(itemsList[i]); 
} 
+0

이것은 목록과 배열에서 작동하지만 IEnumerable에 대해 동일한 작업을 두 번 반복하지 않고 수행해야합니다. – dilbert

+0

아, 네 말이 맞아. 나는 명확성을 위해 코드 예제를 수정했다. 뼈대와 함께 가라. – HitLikeAHammer

1

는 여기에 또 다른 방법 :

private static void Main(string[] args) 
    { 
     var testdata = new[] { "a", "b", "c", "d", "e" }; 

     var action = FirstThenRest<string>(
      s => Console.WriteLine("First: " + s), 
      s => Console.WriteLine("Rest: " + s)); 

     foreach (var s in testdata) 
      action(s); 
    } 

    public static Action<T> FirstThenRest<T>(Action<T> first, Action<T> rest) 
    { 
     Action<T> closure = t => 
          { 
           first(t); 
           closure = rest; 
          }; 

     return t => closure(t); 
    } 

이 출력 :

First: a 
Rest: b 
Rest: c 
Rest: d 
Rest: e 

없음 조건문. : D

EDIT : "Head"와 "Tail"이 더 나은 용어 일지 모르지만 나는 지금 변경하기에는 너무 게으른 편입니다.

관련 문제