4908618aea7c32eb0f94d398b57fa28d

I was just writing up a blog post, and I thought some of the code I wrote as a by-product was quite interesting. The problem is similar to the problem listed at http://refactormycode.com/codes/451-zig-zag-ordering-of-array, but is designed for iterating over two potentially never-ending IEnumerables, instead of finite arrays.

The code I've written works by doing diagonal swipes across the infinite 2d array formed by the two sets, but it has a couple of flaws. The first is that it stores the previous values of the array, which means that it will use up loads memory as the array gets bigger. The second is that it doesn't cater for finite sets of different lengths.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using NUnit.Framework;

namespace MagicMvc.Tests
{
    [TestFixture]
    public class ZigZaggerTests
    {
        IEnumerable<int> NaturalNumbers()
        {
            int i = 0;
            while (true)
            {
                yield return i++;
            }
        }

        public class Tuple<T0, T1>
        {
            public Tuple(T0 first, T1 second)
            {
                this.First = first;
                this.Second = second;
            }

            public T0 First { get; private set; }
            public T1 Second { get; private set; }
        }


        readonly Action<Tuple<int, int>, int, int> assert =
            (tuple, a, b) => Assert.That(tuple.First == a && tuple.Second == b);

        static IEnumerable<Tuple<TX, TY>> ZigZag<TX, TY>(IEnumerable<TX> xs, IEnumerable<TY> ys)
        {
            var xValues = new List<TX>();
            IEnumerator<TX> xEnumerator = xs.GetEnumerator();
            IEnumerator<TY> yEnumerator = ys.GetEnumerator();
            var yValues = new List<TY>();
            while (xEnumerator.MoveNext() && yEnumerator.MoveNext())
            {
                xValues.Add(xEnumerator.Current);
                yValues.Add(yEnumerator.Current);
                for (int i = xValues.Count - 1; i >= 0; i--)
                {
                    yield return new Tuple<TX, TY>(xValues[i], yValues[xValues.Count - i - 1]);
                }
            }
        }

        [Test]
        public void CombineAFuncWithOneParameter()
        {
            Expression<Func<int, bool>> filterOne = i => i != 1;
            Expression<Func<int, bool>> filterTwo = i => i != 2;
            Expression<Func<int, bool>> combined = filterOne.And(filterTwo);
            IQueryable<int> filtered = this.NaturalNumbers().Take(3).AsQueryable().Where(combined);
            Assert.AreEqual(0, filtered.Single());
        }

        [Test]
        public void CombineFuncsWithTwoParameters()
        {
            Expression<Func<int, int, bool>> filterOne = (x, y) => x != y;
            Expression<Func<int, int, bool>> filterTwo = (x, y) => x*2 == y;
        }

        [Test]
        public void TestInfiniteSets()
        {
            List<Tuple<int, int>> tuples = ZigZag(this.NaturalNumbers(), this.NaturalNumbers()).Take(10).ToList();
            this.assert(tuples[0], 0, 0);
            this.assert(tuples[1], 1, 0);
            this.assert(tuples[2], 0, 1);
            this.assert(tuples[3], 2, 0);
            this.assert(tuples[4], 1, 1);
            this.assert(tuples[5], 0, 2);
            this.assert(tuples[6], 3, 0);
            this.assert(tuples[7], 2, 1);
            this.assert(tuples[8], 1, 2);
            this.assert(tuples[9], 0, 3);
        }
    }
}

Refactorings

No refactoring yet !

Your refactoring





Format Copy from initial code

or Cancel