nest yields to return IEnumerable> with lazy evaluation

前端 未结 4 2074
忘掉有多难
忘掉有多难 2021-02-13 16:40

I wrote a LINQ extension method SplitBetween analogous to String.Split.

> new List(){3,4,2,21,3,2,17,16,1}
> .SplitBet         


        
4条回答
  •  粉色の甜心
    2021-02-13 17:17

      public static IEnumerable> SplitBetween(this IEnumerable source, Func separatorSelector, bool includeSeparators = false)
      {
        var state = new SharedState(source, separatorSelector, includeSeparators);
        state.LastList = state.NewList  = new InnerList(state, 0);
        for (; ; )
        {
          if (state.NewList != null)
          {
            var newList = state.NewList;
            state.NewList = null;
            yield return newList.Items();            
          }
          else if (state.IsEnd)
            break;
          else
            state.CheckNext();
        }
      }
      class SharedState
      {
        public SharedState(IEnumerable source, Func separatorSelector, bool includeSeparators)
        {
          this.source = source;
          this.separatorSelector = separatorSelector;
          this.includeSeparators = includeSeparators;
    
          this.iterator = source.GetEnumerator();
    
          this.data = source as IList;
          if (data == null)
          {
            cache = new List();
            data = cache;
          }
        }
        public readonly IEnumerable source;
        readonly IEnumerator iterator; 
        public readonly IList data;
        readonly List cache;
        public readonly Func separatorSelector;
        public readonly bool includeSeparators;
        public int WaveIndex = -1;
        public bool IsEnd = false;
        public InnerList NewList;
        public InnerList LastList;
    
        public void CheckNext()
        {
          WaveIndex++;
          if (!iterator.MoveNext())
          {
            if (LastList.LastIndex == null)
              LastList.LastIndex = WaveIndex;
            IsEnd = true;
          }
          else
          {
            var item = iterator.Current;
            if (cache != null)
              cache.Add(item);
            if (separatorSelector(item))
            {
              LastList.LastIndex = includeSeparators ? WaveIndex + 1 : WaveIndex;
              LastList = NewList = new InnerList(this, WaveIndex + 1);
            }
          }
        }
      }
    
      class InnerList
      {
        public InnerList(SharedState state, int startIndex)
        {
          this.state = state;
          this.StartIndex = startIndex;
        }
        readonly SharedState state;
        public readonly int StartIndex;
        public int? LastIndex;
    
        public IEnumerable Items()
        {
          for (var i = StartIndex; ; ++i)
          {
            if (LastIndex != null && i >= LastIndex)
              break;
            if (i >= state.WaveIndex)
              state.CheckNext();
            if (LastIndex == null || i < LastIndex)
              yield return state.data[i];
          }
        }
      }
    

提交回复
热议问题