fx-sharp  0.1
A collection of functional extensions for C#.
 All Classes Namespaces Files Functions Variables Enumerator
EnumerableExtensions.cs
Go to the documentation of this file.
1 using System;
2 using System.Collections.Generic;
3 using System.Linq;
4 using FxSharp.Utils;
5 using JetBrains.Annotations;
6 
7 namespace FxSharp.Extensions
8 {
9  public static class EnumerableExtensions
10  {
11  /// <summary>
12  /// Convert a single value into an one item-sized enumerable.
13  /// </summary>
14  /// <typeparam name="T"></typeparam>
15  /// <param name="val"></param>
16  /// <returns></returns>
17  public static IEnumerable<T> ToEnumerable<T>(this T val)
18  {
19  yield return val;
20  }
21 
22  /// <summary>
23  /// Similiar to FirstOrDefault but return a Maybe.
24  /// </summary>
25  /// <typeparam name="TSource">The type of the enumerable.</typeparam>
26  /// <param name="source">The enumerable.</param>
27  /// <param name="predicate">The predicate to filter with.</param>
28  /// <returns>Maybe.Nothing(T) if no value matches the predicate.</returns>
29  public static Maybe<TSource> FirstOrNothing<TSource>(
30  [NotNull] this IEnumerable<TSource> source,
31  [NotNull] Func<TSource, bool> predicate)
32  {
33  // ReSharper disable once PossibleMultipleEnumeration
34  Ensure.NotNull(source, "source");
35  Ensure.NotNull(predicate, "predicate");
36 
37  // ReSharper disable once PossibleMultipleEnumeration
38  var enumerable = source as TSource[] ?? source.ToArray();
39 
40  return !enumerable.Any(predicate)
41  ? Maybe.Nothing<TSource>()
42  : Maybe.Just(enumerable.FirstOrDefault(predicate));
43  }
44 
45  /// <summary>
46  /// Similiar to FirstOrDefault but return a Maybe.
47  /// </summary>
48  /// <typeparam name="TSource">The type of the enumerable.</typeparam>
49  /// <param name="source">The enumerable.</param>
50  /// <returns>Maybe.Nothing(T) if no value matches the predicate.</returns>
51  public static Maybe<TSource> FirstOrNothing<TSource>(
52  [NotNull] this IEnumerable<TSource> source)
53  {
54  // ReSharper disable once PossibleMultipleEnumeration
55  Ensure.NotNull(source, "source");
56 
57  // ReSharper disable once PossibleMultipleEnumeration
58  var enumerable = source as TSource[] ?? source.ToArray();
59 
60  return enumerable.Any()
61  ? Maybe.Just(enumerable.FirstOrDefault())
62  : Maybe.Nothing<TSource>();
63  }
64 
65 
66  /// <summary>
67  /// Returns last element of sequence wrapped in Maybe.
68  /// </summary>
69  /// <typeparam name="TSource">The type of the enumerable.</typeparam>
70  /// <param name="source">The enumerable.</param>
71  /// <returns>Maybe.Nothing(T) when sequence is empty.</returns>
72  public static Maybe<TSource> LastOrNothing<TSource>(
73  [NotNull] this IEnumerable<TSource> source)
74  {
75  // ReSharper disable once PossibleMultipleEnumeration
76  Ensure.NotNull(source, "source");
77 
78  // ReSharper disable once PossibleMultipleEnumeration
79  var enumerable = source as TSource[] ?? source.ToArray();
80 
81  return enumerable.Any()
82  ? Maybe.Just(enumerable.LastOrDefault())
83  : Maybe.Nothing<TSource>();
84  }
85 
86  /// <summary>
87  /// Returns last element of sequence which matches the predicate,
88  /// wrapped in Maybe.
89  /// </summary>
90  /// <typeparam name="TSource">The type of the enumerable.</typeparam>
91  /// <param name="source">Maybe.Nothing(T) when sequence is empty.</param>
92  /// <param name="predicate">The predicate to filter with.</param>
93  /// <returns>
94  /// Maybe.Nothing(T) when no element matches the sequence
95  /// or the sequence is empty.
96  /// </returns>
97  public static Maybe<TSource> LastOrNothing<TSource>(
98  [NotNull] this IEnumerable<TSource> source,
99  [NotNull] Func<TSource, bool> predicate)
100  {
101  // ReSharper disable once PossibleMultipleEnumeration
102  Ensure.NotNull(source, "source");
103  Ensure.NotNull(predicate, "predicate");
104 
105  // ReSharper disable once PossibleMultipleEnumeration
106  var enumerable = source as TSource[] ?? source.ToArray();
107 
108  return !enumerable.Any(predicate)
109  ? Maybe.Nothing<TSource>()
110  : Maybe.Just(enumerable.LastOrDefault(predicate));
111  }
112 
113  /// <summary>
114  /// Returns the only element of a sequence, which matches a predicate.
115  /// Returns Option.None(T) when source contains more than one element or
116  /// when the source is empty.
117  /// </summary>
118  /// <typeparam name="TSource">The type of the enumerable.</typeparam>
119  /// <param name="source">
120  /// Option.Some(T) if the source contains exactly one element,
121  /// which matches the predicate.
122  /// Option.None(T) when source contains more than one element
123  /// or when the source is empty.
124  /// </param>
125  /// <param name="predicate">The predicate to filter with.</param>
126  public static Maybe<TSource> SingleOrNothing<TSource>(
127  [NotNull] this IEnumerable<TSource> source,
128  [NotNull] Func<TSource, bool> predicate)
129  {
130  // ReSharper disable once PossibleMultipleEnumeration
131  Ensure.NotNull(source, "source");
132  Ensure.NotNull(predicate, "predicate");
133 
134  // ReSharper disable once PossibleMultipleEnumeration
135  var filtered = source.Where(predicate);
136 
137  using (var enumerator = filtered.GetEnumerator())
138  {
139  if (!enumerator.MoveNext()) return Maybe.Nothing<TSource>();
140  var result = enumerator.Current;
141  if (!enumerator.MoveNext()) return Maybe.Just(result);
142  }
143 
144  return Maybe.Nothing<TSource>();
145  }
146 
147  /// <summary>
148  /// Returns the only element of a sequence.
149  /// Returns Option.None(T) when source contains more than one element or
150  /// when the source is empty.
151  /// </summary>
152  /// <typeparam name="TSource">The type of the enumerable.</typeparam>
153  /// <param name="source">
154  /// Option.Some(T) if the source contains exactly one element.
155  /// Option.None(T) when source contains more than one element
156  /// or when the source is empty.
157  /// </param>
158  public static Maybe<TSource> SingleOrNothing<TSource>(
159  [NotNull] this IEnumerable<TSource> source)
160  {
161  // ReSharper disable once PossibleMultipleEnumeration
162  Ensure.NotNull(source, "source");
163 
164  // ReSharper disable once PossibleMultipleEnumeration
165  using (var enumerator = source.GetEnumerator())
166  {
167  if (!enumerator.MoveNext()) return Maybe.Nothing<TSource>();
168  var result = enumerator.Current;
169  if (!enumerator.MoveNext()) return Maybe.Just(result);
170  }
171  return Maybe.Nothing<TSource>();
172  }
173  }
174 }