更新IEnumerable的Tail扩展方法

This commit is contained in:
Sanchime 2022-05-12 21:58:36 +08:00
parent 537b7280de
commit 6be9bbcb8e
3 changed files with 72 additions and 13 deletions

View File

@ -11,21 +11,77 @@ public static class IEnumerableExtension
public static Func<T, IEnumerable<T>> Return<T>() => t => List(t); public static Func<T, IEnumerable<T>> Return<T>() => t => List(t);
public static Option<T> Head<T>(this IEnumerable<T> list) /// <summary>
/// 将序列内第一条元素转换为<see cref="Option"/>
/// </summary>
/// <param name="source"></param>
/// <typeparam name="T"></typeparam>
/// <returns></returns>
public static Option<T> Head<T>(this IEnumerable<T> source)
{ {
if (list is null) if (source is null)
{ {
return Option.None; return Option.None;
} }
var enumerator = list.GetEnumerator(); var first = source.FirstOrDefault();
return enumerator.MoveNext() ? Option.Some(enumerator.Current) : Option.None; return first is not null ? Option.Some(first) : Option.None;
} }
public static R Match<T, R>(this IEnumerable<T> list, Func<R> Empty, Func<T, IEnumerable<T>, R> Otherwise) /// <summary>
=> list.Head().Match(Empty, (head) => Otherwise(head, list.Skip(1))); /// 给定谓词,查询序列内第一条数据并将其转换为<see cref="Option"/>
/// </summary>
/// <param name="source">数据源</param>
/// <param name="predicate">谓词</param>
/// <typeparam name="T"></typeparam>
/// <returns></returns>
public static Option<T> Head<T>(this IEnumerable<T> source, Func<T, bool> predicate)
{
if (source is null)
{
return Option.None;
}
var first = source.Where(predicate).FirstOrDefault();
return first is not null ? Option.Some(first) : Option.None;
}
public static IEnumerable<R> Map<T, R>(this IEnumerable<T> list, Func<T, R> func) /// <summary>
=> list.Select(func); /// 将序列内最后一个元素转换为<see cref="Option"/>
/// </summary>
/// <param name="source"></param>
/// <typeparam name="T"></typeparam>
/// <returns></returns>
public static Option<T> Tail<T>(this IEnumerable<T> source)
{
if (source is null)
{
return Option.None;
}
var tail = source.LastOrDefault();
return tail is not null ? Option.Some(tail) : Option.None;
}
/// <summary>
/// 给定谓词,查询序列内最后一条数据并将其转换为<see cref="Option"/>
/// </summary>
/// <param name="source">数据源</param>
/// <param name="predicate">谓词</param>
/// <typeparam name="T"></typeparam>
/// <returns></returns>
public static Option<T> Tail<T>(this IEnumerable<T> source, Func<T, bool> predicate)
{
if (source is null)
{
return Option.None;
}
var last = source.Where(predicate).LastOrDefault();
return last is not null ? Option.Some(last) : Option.None;
}
public static R Match<T, R>(this IEnumerable<T> source, Func<R> Empty, Func<T, IEnumerable<T>, R> Otherwise)
=> source.Head().Match(Empty, (head) => Otherwise(head, source.Skip(1)));
public static IEnumerable<R> Map<T, R>(this IEnumerable<T> source, Func<T, R> func)
=> source.Select(func);
/// <summary> /// <summary>
/// 给集合内每个元素执行一个无返回值函数 /// 给集合内每个元素执行一个无返回值函数
@ -37,11 +93,11 @@ public static class IEnumerableExtension
public static IEnumerable<Unit> ForEach<T>(this IEnumerable<T> source, Action<T> action) public static IEnumerable<Unit> ForEach<T>(this IEnumerable<T> source, Action<T> action)
=> source.Map(action.ToFunc()).ToImmutableList(); => source.Map(action.ToFunc()).ToImmutableList();
public static IEnumerable<R> Bind<T, R>(this IEnumerable<T> list, Func<T, IEnumerable<R>> func) public static IEnumerable<R> Bind<T, R>(this IEnumerable<T> source, Func<T, IEnumerable<R>> func)
=> list.SelectMany(func); => source.SelectMany(func);
public static IEnumerable<R> Bind<T, R>(this IEnumerable<T> list, Func<T, Option<R>> func) public static IEnumerable<R> Bind<T, R>(this IEnumerable<T> source, Func<T, Option<R>> func)
=> list.Bind(t => func(t).AsEnumerable()); => source.Bind(t => func(t).AsEnumerable());
private static IEnumerable<T> List<T>(T t) private static IEnumerable<T> List<T>(T t)

View File

@ -107,6 +107,10 @@ public static class OptionExtension
public static Either<L, R> ToEither<L, R>(this Option<L> option, R error) public static Either<L, R> ToEither<L, R>(this Option<L> option, R error)
=> option.IsSome() ? Either.Right(error) : Either.Left(option.Value); => option.IsSome() ? Either.Right(error) : Either.Left(option.Value);
public static Either<L, string> ToEither<L, R>(this Option<L> option, string error)
=> option.IsSome() ? Either.Right(error) : Either.Left(option.Value);
#region Linq式 #region Linq式
public static Option<R> Select<T, R>(this Option<T> source, Func<T, R> mapping) public static Option<R> Select<T, R>(this Option<T> source, Func<T, R> mapping)

View File

@ -49,7 +49,6 @@ public readonly struct Either<TLeft, TRight>
=> Match(l => $"Left({l})", r => $"Right({r})"); => Match(l => $"Left({l})", r => $"Right({r})");
} }
public readonly struct Left<TLeft> public readonly struct Left<TLeft>
{ {
internal TLeft Value { get; } internal TLeft Value { get; }