Skip to content

Commit 50b842d

Browse files
Oraceatifaziz
authored andcommitted
Return isolated windows from Window* methods
This is a squashed merge of PR #655 that closes #652.
1 parent bf15061 commit 50b842d

File tree

6 files changed

+154
-12
lines changed

6 files changed

+154
-12
lines changed

MoreLinq.Test/WindowLeftTest.cs

+45
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,51 @@ public void WindowLeftIsLazy()
2929
new BreakingSequence<int>().WindowLeft(1);
3030
}
3131

32+
[Test]
33+
public void WindowModifiedBeforeMoveNextDoesNotAffectNextWindow()
34+
{
35+
var sequence = Enumerable.Range(0, 3);
36+
using var e = sequence.WindowLeft(2).GetEnumerator();
37+
38+
e.MoveNext();
39+
var window1 = e.Current;
40+
window1[1] = -1;
41+
e.MoveNext();
42+
var window2 = e.Current;
43+
44+
Assert.That(window2[0], Is.EqualTo(1));
45+
}
46+
47+
[Test]
48+
public void WindowModifiedAfterMoveNextDoesNotAffectNextWindow()
49+
{
50+
var sequence = Enumerable.Range(0, 3);
51+
using var e = sequence.WindowLeft(2).GetEnumerator();
52+
53+
e.MoveNext();
54+
var window1 = e.Current;
55+
e.MoveNext();
56+
window1[1] = -1;
57+
var window2 = e.Current;
58+
59+
Assert.That(window2[0], Is.EqualTo(1));
60+
}
61+
62+
[Test]
63+
public void WindowModifiedDoesNotAffectPreviousWindow()
64+
{
65+
var sequence = Enumerable.Range(0, 3);
66+
using var e = sequence.WindowLeft(2).GetEnumerator();
67+
68+
e.MoveNext();
69+
var window1 = e.Current;
70+
e.MoveNext();
71+
var window2 = e.Current;
72+
window2[0] = -1;
73+
74+
Assert.That(window1[1], Is.EqualTo(1));
75+
}
76+
3277
[Test]
3378
public void WindowLeftWithNegativeWindowSize()
3479
{

MoreLinq.Test/WindowRightTest.cs

+45
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,51 @@ public void WindowRightIsLazy()
2929
new BreakingSequence<int>().WindowRight(1);
3030
}
3131

32+
[Test]
33+
public void WindowModifiedBeforeMoveNextDoesNotAffectNextWindow()
34+
{
35+
var sequence = Enumerable.Range(0, 3);
36+
using var e = sequence.WindowRight(2).GetEnumerator();
37+
38+
e.MoveNext();
39+
var window1 = e.Current;
40+
window1[0] = -1;
41+
e.MoveNext();
42+
var window2 = e.Current;
43+
44+
Assert.That(window2[0], Is.EqualTo(0));
45+
}
46+
47+
[Test]
48+
public void WindowModifiedAfterMoveNextDoesNotAffectNextWindow()
49+
{
50+
var sequence = Enumerable.Range(0, 3);
51+
using var e = sequence.WindowRight(2).GetEnumerator();
52+
53+
e.MoveNext();
54+
var window1 = e.Current;
55+
e.MoveNext();
56+
window1[0] = -1;
57+
var window2 = e.Current;
58+
59+
Assert.That(window2[0], Is.EqualTo(0));
60+
}
61+
62+
[Test]
63+
public void WindowModifiedDoesNotAffectPreviousWindow()
64+
{
65+
var sequence = Enumerable.Range(0, 3);
66+
using var e = sequence.WindowRight(2).GetEnumerator();
67+
68+
e.MoveNext();
69+
var window1 = e.Current;
70+
e.MoveNext();
71+
var window2 = e.Current;
72+
window2[0] = -1;
73+
74+
Assert.That(window1[0], Is.EqualTo(0));
75+
}
76+
3277
[Test]
3378
public void WindowRightWithNegativeWindowSize()
3479
{

MoreLinq.Test/WindowTest.cs

+46-1
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,51 @@ public void TestWindowIsLazy()
3434
new BreakingSequence<int>().Window(1);
3535
}
3636

37+
[Test]
38+
public void WindowModifiedBeforeMoveNextDoesNotAffectNextWindow()
39+
{
40+
var sequence = Enumerable.Range(0, 3);
41+
using var e = sequence.Window(2).GetEnumerator();
42+
43+
e.MoveNext();
44+
var window1 = e.Current;
45+
window1[1] = -1;
46+
e.MoveNext();
47+
var window2 = e.Current;
48+
49+
Assert.That(window2[0], Is.EqualTo(1));
50+
}
51+
52+
[Test]
53+
public void WindowModifiedAfterMoveNextDoesNotAffectNextWindow()
54+
{
55+
var sequence = Enumerable.Range(0, 3);
56+
using var e = sequence.Window(2).GetEnumerator();
57+
58+
e.MoveNext();
59+
var window1 = e.Current;
60+
e.MoveNext();
61+
window1[1] = -1;
62+
var window2 = e.Current;
63+
64+
Assert.That(window2[0], Is.EqualTo(1));
65+
}
66+
67+
[Test]
68+
public void WindowModifiedDoesNotAffectPreviousWindow()
69+
{
70+
var sequence = Enumerable.Range(0, 3);
71+
using var e = sequence.Window(2).GetEnumerator();
72+
73+
e.MoveNext();
74+
var window1 = e.Current;
75+
e.MoveNext();
76+
var window2 = e.Current;
77+
window2[0] = -1;
78+
79+
Assert.That(window1[1], Is.EqualTo(1));
80+
}
81+
3782
/// <summary>
3883
/// Verify that a negative window size results in an exception
3984
/// </summary>
@@ -42,7 +87,7 @@ public void TestWindowNegativeWindowSizeException()
4287
{
4388
var sequence = Enumerable.Repeat(1, 10);
4489

45-
AssertThrowsArgument.OutOfRangeException("size",() =>
90+
AssertThrowsArgument.OutOfRangeException("size", () =>
4691
sequence.Window(-5));
4792
}
4893

MoreLinq/Window.cs

+7-8
Original file line numberDiff line numberDiff line change
@@ -52,21 +52,20 @@ public static IEnumerable<IList<TSource>> Window<TSource>(this IEnumerable<TSour
5252
if (i < size)
5353
yield break;
5454

55-
// return the first window (whatever size it may be)
56-
yield return window;
57-
58-
// generate the next window by shifting forward by one item
5955
while (iter.MoveNext())
6056
{
61-
// NOTE: If we used a circular queue rather than a list,
62-
// we could make this quite a bit more efficient.
63-
// Sadly the BCL does not offer such a collection.
57+
// generate the next window by shifting forward by one item
58+
// and do that before exposing the data
6459
var newWindow = new TSource[size];
6560
Array.Copy(window, 1, newWindow, 0, size - 1);
6661
newWindow[size - 1] = iter.Current;
67-
yield return newWindow;
62+
63+
yield return window;
6864
window = newWindow;
6965
}
66+
67+
// return the last window.
68+
yield return window;
7069
}
7170
}
7271

MoreLinq/WindowLeft.cs

+7-2
Original file line numberDiff line numberDiff line change
@@ -71,13 +71,18 @@ public static IEnumerable<IList<TSource>> WindowLeft<TSource>(this IEnumerable<T
7171
window.Add(item);
7272
if (window.Count < size)
7373
continue;
74+
75+
// prepare next window before exposing data
76+
var nextWindow = new List<TSource>(window.Skip(1));
7477
yield return window;
75-
window = new List<TSource>(window.Skip(1));
78+
window = nextWindow;
7679
}
7780
while (window.Count > 0)
7881
{
82+
// prepare next window before exposing data
83+
var nextWindow = new List<TSource>(window.Skip(1));
7984
yield return window;
80-
window = new List<TSource>(window.Skip(1));
85+
window = nextWindow;
8186
}
8287
}
8388
}

MoreLinq/WindowRight.cs

+4-1
Original file line numberDiff line numberDiff line change
@@ -84,8 +84,11 @@ static IEnumerable<IList<TSource>> WindowRightWhile<TSource>(
8484
foreach (var item in source)
8585
{
8686
window.Add(item);
87+
88+
// prepare next window before exposing data
89+
var nextWindow = new List<TSource>(predicate(item, window.Count) ? window : window.Skip(1));
8790
yield return window;
88-
window = new List<TSource>(predicate(item, window.Count) ? window : window.Skip(1));
91+
window = nextWindow;
8992
}
9093
}
9194
}

0 commit comments

Comments
 (0)