forked from topnguyen/Elect
-
Notifications
You must be signed in to change notification settings - Fork 1
/
LinqExtensions.cs
141 lines (121 loc) · 4.38 KB
/
LinqExtensions.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
#region License
//--------------------------------------------------
// <License>
// <Copyright> 2018 © Top Nguyen </Copyright>
// <Url> http://topnguyen.com/ </Url>
// <Author> Top </Author>
// <Project> Elect </Project>
// <File>
// <Name> LinqExtensions.cs </Name>
// <Created> 15/03/2018 6:47:49 PM </Created>
// <Key> fda1b9c5-0690-4191-a1a3-6c9b390c9d56 </Key>
// </File>
// <Summary>
// LinqExtensions.cs is a part of Elect
// </Summary>
// <License>
//--------------------------------------------------
#endregion License
using System;
using System.Collections.Generic;
using System.Linq;
namespace Elect.Core.LinqUtils
{
public static class LinqExtensions
{
public static IEnumerable<TSource> DistinctBy<TSource, TKey>(this IEnumerable<TSource> source,
Func<TSource, TKey> keySelector)
{
var seenKeys = new HashSet<TKey>();
foreach (var element in source)
{
if (seenKeys.Add(keySelector(element)))
{
yield return element;
}
}
}
public static IEnumerable<TSource> RemoveWhere<TSource>(this IEnumerable<TSource> source,
Predicate<TSource> predicate)
{
return source.Where(x => !predicate(x));
}
/// <summary>
/// Continues processing items in a collection until the end condition is true.
/// </summary>
public static IEnumerable<T> TakeUntil<T>(this IEnumerable<T> source, Predicate<T> endCondition)
{
return source.TakeWhile(item => !endCondition(item));
}
/// <summary>
/// Compare Through a predicate every element of a list with the previous one
/// </summary>
/// <param name="collection"></param>
/// <param name="predicate"></param>
/// <typeparam name="T"></typeparam>
/// <returns></returns>
/// <example>
/// var items = new List{int} { 1, 5, 7, 3, 10, 9, 6};
/// var result = items.WherePrevious((first, second) => second > first); => Result is 5, 7, 10
/// </example>
/// <exception cref="ArgumentNullException"></exception>
public static IEnumerable<T> WherePrevious<T>(this IEnumerable<T> collection, Func<T, T, bool> predicate)
{
if (collection == null)
{
throw new ArgumentNullException(nameof(collection));
}
if (predicate == null)
{
throw new ArgumentNullException(nameof(predicate));
}
using (var e = collection.GetEnumerator())
{
e.MoveNext();
var previous = e.Current;
while (e.MoveNext())
{
if (predicate(previous, e.Current))
{
yield return e.Current;
}
previous = e.Current;
}
}
}
/// <summary>
/// Random items position inside the source
/// </summary>
/// <param name="source"></param>
/// <typeparam name="T"></typeparam>
/// <returns></returns>
public static IEnumerable<T> Randomize<T>(this IEnumerable<T> source)
{
var random = new Random();
return source.OrderBy(x => random.Next());
}
/// <summary>
/// ToList() with an extra capacity argument. This can boost the speed of creating the list.
/// </summary>
/// <param name="source"></param>
/// <param name="capacity"></param>
/// <typeparam name="TSource"></typeparam>
/// <returns></returns>
/// <exception cref="ArgumentNullException"></exception>
/// <exception cref="ArgumentOutOfRangeException"></exception>
public static List<TSource> ToList<TSource>(this IEnumerable<TSource> source, int capacity)
{
if (capacity < 0)
{
throw new ArgumentOutOfRangeException(nameof(capacity), "Non-negative number required.");
}
if (source == null)
{
return null;
}
var list = new List<TSource>(capacity);
list.AddRange(source);
return list;
}
}
}