我有以下扩展方法来查找序列中的元素,然后返回两个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))
};
}
Run Code Online (Sandbox Code Playgroud)
否则sequence.ToArray()立即战胜懒惰的要求.但是,如果没有该行,sequence则可以迭代昂贵的迭代次数.而且,取决于调用代码的作用,还有很多次.
这是一个有趣的问题,要解决这个问题,您必须知道什么是“正确”。对于操作的语义,我认为这个定义是有意义的:
我不完全确定我是否正确处理了匹配对象,但我希望您明白这一点。我把很多工作推迟到课堂上PartitionTuple<T>,以便能够偷懒。
public class PartitionTuple<T>
{
IEnumerable<T> source;
IList<T> before, after;
Func<T, bool> partition;
public PartitionTuple(IEnumerable<T> source, Func<T, 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, Func<T, bool> partition)
{
return new PartitionTuple<T>(sequence, partition);
}
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
423 次 |
| 最近记录: |