Help to implement a ZipWithRatio extention method
I'm trying to find a elegant way to write a extention method that might be c开发者_StackOverflowalled MergeWithRatio or ZipWithRatio.
I expect it to have this signature..
public static IEnumerable<T> MergeWithRatio<T>(this IEnumerable<T> source, IEnumerable<T> mergeSequence, int ratio)
{
..
}
Example first.
var source = new[]{1,2,3,4,5,6,7,8,9};
var mergeSeq = new[]{100,200};
var result = source.MergeWithRatio(mergeSeq, 3).ToArray();
result now contains [1, 2, 100, 3, 4, 200, 5, 6, 100, 7, 8, 200, 9]
Summing up: The mergeSeq is looped when/if finished and the yielding stops when 'source' is empty.
If possible I would prefere if the solution was lazy but it is not a requirement.
Any ideas or pointers?
This would work and returns the expected output:
public static IEnumerable<T> MergeWithRatio<T>(this IEnumerable<T> source, IEnumerable<T> mergeSequence, int ratio)
{
int currentRatio = 1;
bool mergeSequenceIsEmpty = !mergeSequence.Any();
using (var mergeEnumerator = mergeSequence.GetEnumerator())
{
foreach (var item in source)
{
yield return item;
currentRatio++;
if (currentRatio == ratio && !mergeSequenceIsEmpty)
{
if (!mergeEnumerator.MoveNext())
{
mergeEnumerator.Reset();
mergeEnumerator.MoveNext();
}
yield return mergeEnumerator.Current;
currentRatio = 1;
}
}
}
}
Here is my implementation:
public static IEnumerable<T> MergeWithRatio<T>(this IEnumerable<T> source, IEnumerable<T> mergeSequence, int ratio)
{
if (source == null)
{
throw new ArgumentNullException("source");
}
if (mergeSequence == null)
{
throw new ArgumentNullException("mergeSequence");
}
if (ratio <= 1)
{
throw new ArgumentOutOfRangeException("ratio must be greater one.");
}
return MergeWithRatioImpl(source, mergeSequence, ratio);
}
private static IEnumerable<T> MergeWithRatioImpl<T>(this IEnumerable<T> source, IEnumerable<T> mergeSequence, int ratio)
{
bool mergeSequenceContainsElements = true;
int i = 1;
ratio--;
using (var sourceEnumerator = source.GetEnumerator())
using (var mergeSequenceEnumerator = mergeSequence.GetEnumerator())
{
while (sourceEnumerator.MoveNext())
{
yield return sourceEnumerator.Current;
if (i++ % ratio == 0)
{
if (!mergeSequenceEnumerator.MoveNext())
{
// ToDo: Should we cache the current values for the case the
// enumerator can't be reset?
mergeSequenceEnumerator.Reset();
mergeSequenceContainsElements = mergeSequenceEnumerator.MoveNext();
}
if (mergeSequenceContainsElements)
{
yield return mergeSequenceEnumerator.Current;
}
}
}
}
}
public static IEnumerable<T> MergeWithRatio<T>(this IEnumerable<T> source, IEnumerable<T> mergeSequence, int ratio)
{
using (IEnumerator<T> sourceEnumerator = source.GetEnumerator(),
mergeSequenceEnumerator = mergeSequence.GetEnumerator())
{
int i = 1;
while (sourceEnumerator.MoveNext())
{
yield return sourceEnumerator.Current;
i++;
if (i == ratio)
{
if (!mergeSequenceEnumerator.MoveNext())
{
mergeSequenceEnumerator.Reset();
mergeSequenceEnumerator.MoveNext();
}
yield return mergeSequenceEnumerator.Current;
i = 1;
}
}
}
}
Plus some checks on mergeSequenceEnumerator.MoveNext()
, ratio
input value`, etc.
精彩评论