문제

시퀀스의 마지막 항목을 제외한 모든 항목을 제공하는 방법이 필요했습니다.이것은 나의 현재 구현입니다.

    public static IEnumerable<T> SkipLast<T>(this IEnumerable<T> source)
    {
        using (IEnumerator<T> iterator = source.GetEnumerator())
        {
            if(iterator.MoveNext())
                while(true)
                {
                    var current = iterator.Current;
                    if(!iterator.MoveNext())
                        yield break;
                    yield return current;
                }
        }
    }

내가 필요한 것은 마지막 항목을 제외한 모든 항목에 대해 작업을 수행하는 것입니다.제 경우에는 다양한 속성을 가진 일련의 개체가 있습니다.그런 다음 날짜별로 주문한 다음 가장 최근 항목(주문 후 마지막 항목)을 제외한 모든 항목을 조정해야 합니다.

사실 저는 아직 이러한 열거자나 그런 것에 별로 관심이 없고 여기에 물어볼 사람도 없습니다. :p 제가 궁금한 것은 이것이 좋은 구현인지 아니면 제가 어딘가에서 작거나 큰 실수를 저질렀는지입니다.아니면 문제를 해결하는 것이 이상한 것일 수도 있습니다.

좀 더 일반적인 구현이 가능했을 것 같습니다. AllExceptMaxBy 방법.그런 종류의 것이기 때문입니다.그만큼 더Linq 가지고있다 MaxBy 그리고 MinBy 메서드와 내 메서드는 동일한 작업을 수행해야 하지만 최대 또는 최소 항목을 제외한 모든 항목을 반환해야 합니다.

도움이 되었습니까?

해결책

"마지막 요소"는 Markov 중지 지점이 아니기 때문에 이는 까다롭습니다.다음 요소를 얻으려고 시도하기 전까지는 마지막 요소에 도달했다는 것을 알 수 없습니다.가능하지만 영구적으로 "뒤에 있는 한 요소"가 되는 것을 꺼리지 않는 경우에만 가능합니다.이것이 기본적으로 현재 구현이 수행하는 작업이며 괜찮아 보이지만 약간 다르게 작성하겠습니다.

대체 접근 방식은 다음을 사용하는 것입니다. foreach, 첫 번째 반복이 아닌 한 항상 이전에 반환된 값을 생성합니다.

public static IEnumerable<T> SkipLast<T>(this IEnumerable<T> source)
{
    T previous = default(T);
    bool first = true;
    foreach (T element in source)
    {
        if (!first)
        {
            yield return previous;
        }
        previous = element;
        first = false;
    }
}

코드에 더 가까운 또 다른 옵션은 다음과 같습니다.

public static IEnumerable<T> SkipLast<T>(this IEnumerable<T> source)
{
    using (IEnumerator<T> iterator = source.GetEnumerator())
    {
        if(!iterator.MoveNext())
        {
            yield break;
        }
        T previous = iterator.Current;
        while (iterator.MoveNext())
        {
            yield return previous;
            previous = iterator.Current;
        }
    }
}

이는 매우 깊게 중첩되는 것을 방지하고(시퀀스가 비어 있는 경우 조기 종료를 수행하여) 대신에 "실제" while 조건을 사용합니다. while(true)

다른 팁

당신의 구현은 나에게 완벽하게 좋아 보인다 - 아마도 내가 할 방법 일 것이다.

당신의 상황과 관련하여 제안 할 수있는 유일한 단순화는 목록을 주문하는 것입니다. 다른 방법 (즉, 내림차순이 아니라 오름차순). 코드에 적합하지는 않지만 간단히 사용할 수 있습니다. collection.Skip(1) 가장 최근의 항목을 제외한 모든 항목을 가져옵니다.

게시물에 표시되지 않은 이유로 불가능한 경우 현재 구현에 전혀 문제가되지 않습니다.

.NET 3.5를 사용하는 경우 사용할 수 있다고 생각합니다.

public static IEnumerable<T> SkipLast<T>(this IEnumerable<T> source)
{
  return source.TakeWhile((item, index) => index < source.Count() - 1))
}
public static IEnumerable<T> SkipLast<T>(this IEnumerable<T> source)
{
    if (!source.Any())
    {
        yield break;
    }
    Queue<T> items = new Queue<T>();
    items.Enqueue(source.First());
    foreach(T item in source.Skip(1))
    {
        yield return items.Dequeue();
        items.Enqueue(item);
    }
}

(오래된 답변 폐기;이 코드는 테스트되었고 작동합니다.) 인쇄
첫 번째

첫 번째

제삼


public static class ExtNum{
  public static IEnumerable skipLast(this IEnumerable source){
    if ( ! source.Any())
      yield break;
    for (int i = 0 ; i <=source.Count()-2 ; i++ )
      yield return source.ElementAt(i);
    yield break;
  }
}
class Program
{
  static void Main( string[] args )
  {
    Queue qq = new Queue();
    qq.Enqueue("first");qq.Enqueue("second");qq.Enqueue("third");
    List lq = new List();
    lq.Add("FIRST"); lq.Add("SECOND"); lq.Add("THIRD"); lq.Add("FOURTH");
    foreach(string s1 in qq.skipLast())
      Console.WriteLine(s1);
    foreach ( string s2 in lq.skipLast())
      Console.WriteLine(s2);
  }
}
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top