加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

c# – 使用LINQ进行Lazily分区序列

发布时间:2020-12-15 08:43:44 所属栏目:百科 来源:网络整理
导读:我有以下扩展方法来查找序列中的元素,然后返回两个IEnumerable T s:一个包含该元素之前的所有元素,一个包含该元素和后面的所有元素.我更喜欢这种方法是懒惰的,但我还没有找到办法做到这一点.任何人都可以提出解决方案吗? public static PartitionTupleT Pa
我有以下扩展方法来查找序列中的元素,然后返回两个IEnumerable< T> s:一个包含该元素之前的所有元素,一个包含该元素和后面的所有元素.我更喜欢这种方法是懒惰的,但我还没有找到办法做到这一点.任何人都可以提出解决方案吗?
public static PartitionTuple<T> Partition<T>(this IEnumerable<T> sequence,Func<T,bool> partition)
{
    var a = sequence.ToArray();
    return new PartitionTuple<T>
    {
        Before = a.TakeWhile(v => !partition(v)),After = a.SkipWhile(v => !partition(v))
    };
}

执行sequence.ToArray()会立即失去懒惰的要求.然而,没有该行,可以迭代昂贵的迭代序列两次.而且,取决于调用代码的作用,还有很多次.

解决方法

这是一个有趣的问题,要做到正确,你必须知道“正确”是什么.对于操作的语义,我认为这个定义是有道理的:

>即使生成的序列被多次枚举,源序列也只被枚举一次.
>在枚举其中一个结果之前,不会枚举源序列.
>每个结果都应该可以独立枚举.
>如果源序列发生变化,则未定义将发生什么.

我不完全确定我正确处理了匹配对象,但我希望你能得到这个想法.我将很多工作推迟到PartitionTuple< T>上课可以偷懒.

public class PartitionTuple<T>
{
  IEnumerable<T> source;
  IList<T> before,after;
  Func<T,bool> partition;

  public PartitionTuple(IEnumerable<T> source,bool> partition)
  {
    this.source = source;
    this.partition = partition;
  }

  private void EnsureMaterialized()
  {
    if(before == null)
    {
      before = new List<T>();
      after = new List<T>();

      using(var enumerator = source.GetEnumerator())
      {
        while(enumerator.MoveNext() && !partition(enumerator.Current))
        {
          before.Add(enumerator.Current);   
        }

        while(!partition(enumerator.Current) && enumerator.MoveNext());

        while(enumerator.MoveNext())
        {
          after.Add(enumerator.Current);
        }
      }
    }
  }

  public IEnumerable<T> Before 
  { 
    get
    {
      EnsureMaterialized();
      return before;
    }
  }

  public IEnumerable<T> After
  {
    get
    {
      EnsureMaterialized();
      return after;
    }
  }
}

public static class Extensions
{
  public static PartitionTuple<T> Partition<T>(this IEnumerable<T> sequence,bool> partition)
  {
    return new PartitionTuple<T>(sequence,partition);
  }
}

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读