-
-
Notifications
You must be signed in to change notification settings - Fork 9
/
DistinctUntilChanged.cs
152 lines (144 loc) · 4.55 KB
/
DistinctUntilChanged.cs
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
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
namespace SuperLinq;
public static partial class SuperEnumerable
{
/// <summary>
/// Returns consecutive distinct elements by using the default equality comparer to compare values.
/// </summary>
/// <typeparam name="TSource">
/// Source sequence element type.
/// </typeparam>
/// <param name="source">
/// Source sequence.
/// </param>
/// <returns>
/// Sequence without adjacent non-distinct elements.
/// </returns>
/// <exception cref="ArgumentNullException">
/// <paramref name="source"/> is <see langword="null"/>.
/// </exception>
/// <remarks>
/// <para>
/// This method uses deferred execution semantics and streams its results.
/// </para>
/// </remarks>
public static IEnumerable<TSource> DistinctUntilChanged<TSource>(this IEnumerable<TSource> source)
{
return DistinctUntilChanged(source, Identity, comparer: null);
}
/// <summary>
/// Returns consecutive distinct elements by using the specified equality comparer to compare values.
/// </summary>
/// <typeparam name="TSource">
/// Source sequence element type.
/// </typeparam>
/// <param name="source">
/// Source sequence.
/// </param>
/// <param name="comparer">
/// Comparer used to compare values.
/// </param>
/// <returns>
/// Sequence without adjacent non-distinct elements.
/// </returns>
/// <exception cref="ArgumentNullException">
/// <paramref name="source"/> is <see langword="null"/>.
/// </exception>
/// <remarks>
/// <para>
/// This method uses deferred execution semantics and streams its results.
/// </para>
/// </remarks>
public static IEnumerable<TSource> DistinctUntilChanged<TSource>(this IEnumerable<TSource> source, IEqualityComparer<TSource>? comparer)
{
ArgumentNullException.ThrowIfNull(source);
return DistinctUntilChanged(source, Identity, comparer);
}
/// <summary>
/// Returns consecutive distinct elements based on a key value by using the specified equality comparer to
/// compare key values.
/// </summary>
/// <typeparam name="TSource">
/// Source sequence element type.
/// </typeparam>
/// <typeparam name="TKey">
/// Key type.
/// </typeparam>
/// <param name="source">
/// Source sequence.
/// </param>
/// <param name="keySelector">
/// Key selector.
/// </param>
/// <returns>
/// Sequence without adjacent non-distinct elements.
/// </returns>
/// <exception cref="ArgumentNullException">
/// <paramref name="source"/> or <paramref name="keySelector"/> is <see langword="null"/>.
/// </exception>
/// <remarks>
/// <para>
/// This method uses deferred execution semantics and streams its results.
/// </para>
/// </remarks>
public static IEnumerable<TSource> DistinctUntilChanged<TSource, TKey>(this IEnumerable<TSource> source, Func<TSource, TKey> keySelector)
{
return DistinctUntilChanged(source, keySelector, comparer: null);
}
/// <summary>
/// Returns consecutive distinct elements based on a key value by using the specified equality comparer to
/// compare key values.
/// </summary>
/// <typeparam name="TSource">
/// Source sequence element type.
/// </typeparam>
/// <typeparam name="TKey">
/// Key type.
/// </typeparam>
/// <param name="source">
/// Source sequence.
/// </param>
/// <param name="keySelector">
/// Key selector.
/// </param>
/// <param name="comparer">
/// Comparer used to compare key values.
/// </param>
/// <returns>
/// Sequence without adjacent non-distinct elements.
/// </returns>
/// <exception cref="ArgumentNullException">
/// <paramref name="source"/> or <paramref name="keySelector"/> is <see langword="null"/>.
/// </exception>
/// <remarks>
/// <para>
/// This method uses deferred execution semantics and streams its results.
/// </para>
/// </remarks>
public static IEnumerable<TSource> DistinctUntilChanged<TSource, TKey>(
this IEnumerable<TSource> source,
Func<TSource, TKey> keySelector,
IEqualityComparer<TKey>? comparer
)
{
ArgumentNullException.ThrowIfNull(source);
ArgumentNullException.ThrowIfNull(keySelector);
return Core(source, keySelector, comparer ?? EqualityComparer<TKey>.Default);
static IEnumerable<TSource> Core(IEnumerable<TSource> source, Func<TSource, TKey> keySelector, IEqualityComparer<TKey> comparer)
{
using var e = source.GetEnumerator();
if (!e.MoveNext())
yield break;
yield return e.Current;
var lastKey = keySelector(e.Current);
while (e.MoveNext())
{
var nextKey = keySelector(e.Current);
if (!comparer.Equals(lastKey, nextKey))
{
yield return e.Current;
lastKey = nextKey;
}
}
}
}
}