Open GoogleCodeExporter opened 9 years ago
Here's my first attempt at this. It produces the result atleast.
public IEnumerable<T> Interleave<T>(params IEnumerable<T>[] sequencesToInterleave)
{
var ls = sequencesToInterleave;
var lsl = ls.Length;
List<IEnumerator<T>> ies = new List<IEnumerator<T>>(lsl);
for (int i = 0; i < lsl; i++)
{
var en = ls[i].GetEnumerator();
ies.Add(en);
//en.MoveNext();
}
while (true)
{
for (int i = 0; i < lsl; i++)
{
var e=ies[i];
if (!e.MoveNext()) { e.Reset(); if (!e.MoveNext()) continue; }
yield return e.Current;
}
}
}
Original comment by virtan...@gmail.com
on 9 May 2014 at 1:06
This variation should stop the yielding once the longest enumerable reaches its
end... Not sure I'm happy with how it returns 6 of the non-numeric chars for
the test above while the longest enum has 5 numeric chars. I don't know how to
fix this yet.
public static IEnumerable<T> InterleaveForLongest<T>(params IEnumerable<T>[] sequencesToInterleave)
{
var ls = sequencesToInterleave;
var lsl = ls.Length;
bool[] resets = new bool[lsl];
List<IEnumerator<T>> ies = new List<IEnumerator<T>>(lsl);
for (int i = 0; i < lsl; i++) ies.Add(ls[i].GetEnumerator());
while (true)
{
for (int i = 0; i < lsl; i++)
{
var e = ies[i];
if (!e.MoveNext()) {
e.Reset(); resets[i] = true;
if (resets.All(x => x == true)) yield break;
if (!e.MoveNext()) continue;
}
yield return e.Current;
}
}
}
Original comment by virtan...@gmail.com
on 9 May 2014 at 1:23
Here's the final code I ended up with for now. I needed to group some data by
custom key and then interleave the values of each group...
var g = data.GroupBy(x => x.type);
foreach (var item in InterleaveForLongestG(g))
Console.WriteLine(item.ToString());
public static IEnumerable<T> InterleaveForLongestG<K, T>(IEnumerable<IGrouping<K, T>> sequencesToInterleave)
{
var ls = sequencesToInterleave.ToList();
var lsl = ls.Count;
bool[] resets = new bool[lsl];
List<IEnumerator<T>> ies = new List<IEnumerator<T>>(lsl);
for (int i = 0; i < lsl; i++) ies.Add(ls[i].ToList().GetEnumerator());
while (true)
{
for (int i = 0; i < lsl; i++)
{
var e = ies[i];
if (!e.MoveNext())
{
e.Reset(); resets[i] = true;
if (resets.All(x => x == true)) yield break;
if (!e.MoveNext()) continue;
}
yield return e.Current;
}
}
}
Original comment by virtan...@gmail.com
on 9 May 2014 at 1:58
Turns out I also needed a predicate for more control. Here's hopefully the
final things I ended up using.
public static IEnumerable<T> EnumInfiniteInterleaved<T>(Func<T, bool> predicate, params IEnumerable<T>[] sequencesContractoInterleave)
{
var ls = sequencesContractoInterleave;
var lsl = ls.Length;
if (lsl < 2) throw new ArgumentOutOfRangeException("Atleast two sequences required");
List<IEnumerator<T>> ies = new List<IEnumerator<T>>(lsl);
for (int i = 0; i < lsl; i++) ies.Add(ls[i].GetEnumerator());
while (true)
{
for (int i = 0; i < lsl; i++)
{
var e = ies[i];
nxt:
if (!e.MoveNext()) { e.Reset(); if (!e.MoveNext()) continue; }
if (!predicate(e.Current)) goto nxt;
yield return e.Current;
}
}
}
public static IEnumerable<T> EnumInfinite<T>(Func<T, bool> predicate, IEnumerable<T> source)
{
if (source == null) yield break; // be a gentleman
IEnumerator<T> e = source.GetEnumerator();
iterateAllAndBackToStart:
while (e.MoveNext())
{
var c = e.Current;
if (predicate(e.Current)) yield return c;
}
e.Reset();
goto iterateAllAndBackToStart;
}
Original comment by virtan...@gmail.com
on 9 May 2014 at 1:40
Original issue reported on code.google.com by
virtan...@gmail.com
on 9 May 2014 at 12:18