AnantLabs / morelinq

Automatically exported from code.google.com/p/morelinq
Apache License 2.0
0 stars 0 forks source link

Interleave irregular enumerables with circular strategy #89

Open GoogleCodeExporter opened 9 years ago

GoogleCodeExporter commented 9 years ago
result: !a1!b2!c3!a4!b5!c1!a2!b3!c4!a5!b1!c2!a3!b4!c5!a1... (Hope I got that 
right, you get the idea). The length of the IEnumerables is unknown of course 
and the result should be lazy-evaluated.

There may already be a way to do this but I didn't see anything obvious like 
this:

public static IEnumerable<T> Interleave<T>(params IEnumerable<T>[] 
sequencesToInterleave)
{
 ... 
}

foreach (var item in Interleave(new string[] { "!" }, new string[] { "a", "b", 
"c" }, new string[] { "1", "2", "3", "4", "5" }))
{
                    Console.Write(item.ToString());
}

Original issue reported on code.google.com by virtan...@gmail.com on 9 May 2014 at 12:18

GoogleCodeExporter commented 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

GoogleCodeExporter commented 9 years ago
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