-
Notifications
You must be signed in to change notification settings - Fork 0
/
EnumerableExtensions.cs
120 lines (107 loc) · 4.35 KB
/
EnumerableExtensions.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
using System;
using System.Collections.Generic;
using System.Linq;
namespace FunLinq
{
public static class EnumerableExtensions
{
public static IEnumerable<TResult> LeftOuterJoin<TOuter, TInner, TKey, TResult>(
this IEnumerable<TOuter> outer,
IEnumerable<TInner> inner,
Func<TOuter, TKey> outerKeySelector,
Func<TInner, TKey> innerKeySelector,
Func<TOuter, TInner, TResult> resultSelector)
{
return outer.GroupJoin(inner,
outerKeySelector,
innerKeySelector,
(outerItem, innerGroup) => new {
Outer = outerItem,
InnerGroup = innerGroup
})
.SelectMany(group => group.InnerGroup.DefaultIfEmpty(),
(group, innerGroup) => resultSelector(group.Outer, innerGroup));
}
public static IEnumerable<TResult> CrossJoin<TFirst, TSecond, TResult>(
this IEnumerable<TFirst> firstSequence,
IEnumerable<TSecond> secondSequence,
Func<TFirst, TSecond, TResult> resultSelector)
{
return firstSequence.SelectMany(first =>
secondSequence.Select(second => resultSelector(first, second)));
}
public static void Each<T>(this IEnumerable<T> enumeration, Action<T> action)
{
foreach(T item in enumeration)
{
action(item);
}
}
public static IEnumerable<T> Cycle<T>(this IEnumerable<T> enumeration)
{
while (true) {
foreach (T item in enumeration)
{
yield return item;
}
}
}
public static IEnumerable<IEnumerable<T>> Batch<T>(this IEnumerable<T> source, int batchSize)
{
using (var enumerator = source.GetEnumerator())
{
while (enumerator.MoveNext())
{
yield return YieldBatchElements(enumerator, batchSize - 1);
}
}
}
private static IEnumerable<T> YieldBatchElements<T>(IEnumerator<T> source, int batchSize)
{
yield return source.Current;
for (int i = 0; i < batchSize && source.MoveNext(); i++)
{
yield return source.Current;
}
}
public static IEnumerable<IEnumerable<TSource>> Break<TSource>(this IEnumerable<TSource> source,
Predicate<TSource> predicate)
{
using (var enumerator = source.GetEnumerator())
{
while (enumerator.MoveNext())
{
yield return BreakWhere(enumerator, predicate);
}
}
}
private static IEnumerable<T> BreakWhere<T>(IEnumerator<T> enumerator,
Predicate<T> predicate)
{
do
{
yield return enumerator.Current;
} while (!predicate(enumerator.Current) && enumerator.MoveNext());
}
public static Tuple<IEnumerable<TSource>, IEnumerable<TSource>>
Partition<TSource>(this IEnumerable<TSource> source, Func<TSource, bool> predicate)
{
var positives = source.Where(predicate);
var negatives = source.Where(item => !predicate(item));
return new Tuple<IEnumerable<TSource>, IEnumerable<TSource>>(positives, negatives);
}
public static IEnumerable<IEnumerable<TSource>>
Transpose<TSource>(this IEnumerable<IEnumerable<TSource>> source)
{
return source
.SelectMany(x => x.Select((item, columnIndex) => new Tuple<TSource, int>(item, columnIndex)))
.GroupBy(x => x.Item2).OrderBy(x => x.Key) //Group by column index
.Select(x => x.Select(y => y.Item1));
}
public static Tuple<IEnumerable<TFirst>, IEnumerable<TSecond>>
Unzip<TFirst, TSecond> (this IEnumerable<Tuple<TFirst,TSecond>> source)
{
return new Tuple<IEnumerable<TFirst>, IEnumerable<TSecond>>(source.Select(x => x.Item1), source.Select(x => x.Item2));
}
}
}