Skip to content

Commit 9ee0830

Browse files
committed
Improve Window
1 parent 74f4250 commit 9ee0830

File tree

2 files changed

+17
-24
lines changed

2 files changed

+17
-24
lines changed

MoreLinq/Extensions.g.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6661,7 +6661,7 @@ public static partial class WindowExtension
66616661
/// <param name="size">The size (number of elements) in each window</param>
66626662
/// <returns>A series of sequences representing each sliding window subsequence</returns>
66636663

6664-
public static IEnumerable<IList<TSource>> Window<TSource>(this IEnumerable<TSource> source, int size)
6664+
public static IEnumerable<IReadOnlyList<TSource>> Window<TSource>(this IEnumerable<TSource> source, int size)
66656665
=> MoreEnumerable.Window(source, size);
66666666

66676667
}

MoreLinq/Window.cs

Lines changed: 16 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -34,38 +34,31 @@ public static partial class MoreEnumerable
3434
/// <param name="size">The size (number of elements) in each window</param>
3535
/// <returns>A series of sequences representing each sliding window subsequence</returns>
3636

37-
public static IEnumerable<IList<TSource>> Window<TSource>(this IEnumerable<TSource> source, int size)
37+
public static IEnumerable<IReadOnlyList<TSource>> Window<TSource>(this IEnumerable<TSource> source, int size)
3838
{
3939
if (source == null) throw new ArgumentNullException(nameof(source));
40-
if (size <= 0) throw new ArgumentOutOfRangeException(nameof(size));
40+
if (size < 0) throw new ArgumentOutOfRangeException(nameof(size));
4141

42-
return _(); IEnumerable<IList<TSource>> _()
42+
return _(); IEnumerable<IReadOnlyList<TSource>> _()
4343
{
44-
using var iter = source.GetEnumerator();
44+
var cache = new List<TSource>();
4545

46-
// generate the first window of items
47-
var window = new TSource[size];
48-
int i;
49-
for (i = 0; i < size && iter.MoveNext(); i++)
50-
window[i] = iter.Current;
46+
using var enumerator = source.GetEnumerator();
5147

52-
if (i < size)
53-
yield break;
48+
var hasNext = true;
49+
bool MoveNext() => hasNext && (hasNext = enumerator.MoveNext());
5450

55-
// return the first window (whatever size it may be)
56-
yield return window;
51+
for (var i = 0; i < size - 1 && MoveNext(); i++)
52+
{
53+
cache.Add(enumerator.Current);
54+
}
5755

58-
// generate the next window by shifting forward by one item
59-
while (iter.MoveNext())
56+
var offset = 0;
57+
while (MoveNext())
6058
{
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.
64-
var newWindow = new TSource[size];
65-
Array.Copy(window, 1, newWindow, 0, size - 1);
66-
newWindow[size - 1] = iter.Current;
67-
yield return newWindow;
68-
window = newWindow;
59+
cache.Add(enumerator.Current);
60+
yield return new WindowedList<TSource>(cache, offset, cache.Count - offset);
61+
offset++;
6962
}
7063
}
7164
}

0 commit comments

Comments
 (0)