首页 / 后端开发 / 正文

[LINQ]收集.NET/C#应用程序开发中一些好的/有用的关于LINQ的非微软官方的静态扩展方法

2107 1 发布于: 2018-04-27 读完约需26分钟

前言

在.NET/C#的应用程序开发中,有了LINQ以及静态扩展方法,我们可以使用它们解决一些泛型的问题。

System.Linq这个命名空间下,微软为我们提供了比较全面的关于LINQ操作的静态扩展方法。

除了System.Linq命名空间下提供的静态扩展方法外,你还有哪些关于LINQ操作的静态扩展方法分享呢,本文就收集了一些有用的关于LINQ的非官方内置的静态扩展方法,供大家参考。

Append & Prepend

public static IEnumerable<T> Append<T>(this IEnumerable<T> source, T element)
{
    if (source == null)
        throw new ArgumentNullException("source");
    return concatIterator(element, source, false);
}

public static IEnumerable<T> Prepend<T>(this IEnumerable<T> tail, T head)
{
    if (tail == null)
        throw new ArgumentNullException("tail");
    return concatIterator(head, tail, true);
}

private static IEnumerable<T> concatIterator<T>(T extraElement,
    IEnumerable<T> source, bool insertAtStart)
{
    if (insertAtStart)
        yield return extraElement;
    foreach (var e in source)
        yield return e;
    if (!insertAtStart)
        yield return extraElement;
}

Each

 public static void Each<T>(this IEnumerable<T> items, Action<T> action)
 {
   foreach (var i in items)
      action(i);
 }

ToQueue && ToStack

public static Queue<T> ToQueue<T>(this IEnumerable<T> source)
{
    if (source == null)
        throw new ArgumentNullException("source");
    return new Queue<T>(source);
}


public static Stack<T> ToStack<T>(this IEnumerable<T> source)
{
    if (source == null)
        throw new ArgumentNullException("source");
    return new Stack<T>(source);
}

IsEmpty

public static bool IsEmpty<T>(this IEnumerable<T> source)
{
    return !source.Any();
}

In & NotIn

public static bool In<T>(this T value, params T[] values)
{
    if (values == null)
        return false;

    if (values.Contains<T>(value))
        return true;

    return false;
}


public static bool In<T>(this T value, IEnumerable<T> values)
{
    if (values == null)
        return false;

    if (values.Contains<T>(value))
        return true;

    return false;
}


public static bool NotIn<T>(this T value, params T[] values)
{
    return In(value, values) == false;
}


public static bool NotIn<T>(this T value, IEnumerable<T> values)
{
    return In(value, values) == false;
}

JoinString

public static string JoinString<T>(this IEnumerable<T> values,
    string separator = null, string prefix = null, string suffix = null)
{
    if (values == null)
        throw new ArgumentNullException("values");

    using (var enumerator = values.GetEnumerator())
    {
        if (!enumerator.MoveNext())
            return "";
        StringBuilder sb = new StringBuilder();
        sb.Append(prefix).Append(enumerator.Current.ToString()).Append(suffix);
        while (enumerator.MoveNext())
            sb.Append(separator).Append(prefix)
              .Append(enumerator.Current.ToString()).Append(suffix);
        return sb.ToString();
    }
}

调用示例:

var a = (new[] { "Paris", "London", "Tokyo" }).JoinString(", ", "[", "]");

输出结果:[Paris], [London], [Tokyo]

Shuffle

private static Random _rand = new Random();
public static IEnumerable<T> Shuffle<T>(this IEnumerable<T> source)
{
    var items = source == null ? new T[] { } : source.ToArray();
    var count = items.Length;
    while(count > 0)
    {
        int toReturn = _rand.Next(0, count);
        yield return items[toReturn];
        items[toReturn] = items[count - 1];
        count--;
    }
}

MinElement

public static T MinElement<T, TValue>(this IEnumerable<T> source,
        Func<T, TValue> valueSelector) where TValue : IComparable<TValue>
{
    if (source == null)
        throw new ArgumentNullException("source");
    if (valueSelector == null)
        throw new ArgumentNullException("valueSelector");
    using (var enumerator = source.GetEnumerator())
    {
        if (!enumerator.MoveNext())
            throw new InvalidOperationException("source contains no elements.");
        T minElem = enumerator.Current;
        TValue minValue = valueSelector(minElem);
        while (enumerator.MoveNext())
        {
            TValue value = valueSelector(enumerator.Current);
            if (value.CompareTo(minValue) < 0)
            {
                minValue = value;
                minElem = enumerator.Current;
            }
        }
        return minElem;
    }
}

IndexOf

public static int IndexOf<T>(this IEnumerable<T> source, Func<T, bool> condition)
{
    if (source == null)
        throw new ArgumentNullException("source");
    if (condition == null)
        throw new ArgumentNullException("condition");
    int index = 0;
    foreach (var v in source)
    {
        if (condition(v))
            return index;
        index++;
    }
    return -1;
}

Chunks

public static IEnumerable<T[]> Chunks<T>(this IEnumerable<T> xs, int size, bool returnRest = false)
{
    var curr = new T[size];

    int i = 0;

    foreach (var x in xs)
    {
        if (i == size)
        {
            yield return curr;
            i = 0;
            curr = new T[size];
        }

        curr[i++] = x;
    }

    if (returnRest)
        yield return curr.Take(i).ToArray();
}

ToHashSet

public static HashSet<T> ToHashSet<T>(this IEnumerable<T> items)
{
    return new HashSet<T>(items);
}

InsertBetween

public static IEnumerable<T> InsertBetween<T>(this IEnumerable<T> source, T extraElement)
{
    return source.SelectMany(val => new[] { extraElement, val }).Skip(1);
}

EmptyIfNull

public static IEnumerable<T> EmptyIfNull<T>(this IEnumerable<T> source)
{
    return source ?? Enumerable.Empty<T>();
}

One, Two, MoreThanOne, AtLeast, AnyAtAll

public static bool One<T>(this IEnumerable<T> enumerable)
{
    using (var enumerator = enumerable.GetEnumerator())
        return enumerator.MoveNext() && !enumerator.MoveNext();
}

public static bool Two<T>(this IEnumerable<T> enumerable)
{
    using (var enumerator = enumerable.GetEnumerator())
        return enumerator.MoveNext() && enumerator.MoveNext() && !enumerator.MoveNext();
}

public static bool MoreThanOne<T>(this IEnumerable<T> enumerable)
{
    return enumerable.Skip(1).Any();
}

public static bool AtLeast<T>(this IEnumerable<T> enumerable, int count)
{
    using (var enumerator = enumerable.GetEnumerator())
        for (var i = 0; i < count; i++)
            if (!enumerator.MoveNext())
                return false;
    return true;
}

public static bool AnyAtAll<T>(this IEnumerable<T> enumerable)
{
    return enumerable != null && enumerable.Any();
}

SkipLast & TakeLast

public static IEnumerable<T> SkipLast<T>(this IEnumerable<T> source, int count)
{
    if (source == null)
        throw new ArgumentNullException("source");
    if (count < 0)
        throw new ArgumentOutOfRangeException("count",
            "count cannot be negative.");
    if (count == 0)
        return source;
    return skipLastIterator(source, count);
}
private static IEnumerable<T> skipLastIterator<T>(IEnumerable<T> source,
    int count)
{
    var queue = new T[count];
    int headtail = 0;
    int collected = 0;

    foreach (var item in source)
    {
        if (collected < count)
        {
            queue[headtail] = item;
            headtail++;
            collected++;
        }
        else
        {
            if (headtail == count) headtail = 0;
            yield return queue[headtail];
            queue[headtail] = item;
            headtail++;
        }
    }
}


public static IEnumerable<T> TakeLast<T>(this IEnumerable<T> source, int count)
{
    if (source == null)
        throw new ArgumentNullException("source");
    if (count < 0)
        throw new ArgumentOutOfRangeException("count",
            "count cannot be negative.");
    if (count == 0)
        return new T[0];

    var queue = new Queue<T>(count + 1);
    foreach (var item in source)
    {
        if (queue.Count == count)
            queue.Dequeue();
        queue.Enqueue(item);
    }
    return queue.AsEnumerable();
}

Duplicates

public static IEnumerable<T> Duplicates<T, TKey>(this IEnumerable<T> source,
    Func<T, TKey> keySelector = null, IEqualityComparer<TKey> comparer = null)
{
    source.ThrowIfNull("source");
    keySelector = keySelector ?? new Func<T, TKey>(x => x);
    comparer = comparer ?? EqualityComparer<TKey>.Default;

    return source.GroupBy(keySelector, comparer)
        .Where(g => g.CountAtLeast(2))
        .SelectMany(g => g);
}

版权声明:本作品系原创,版权归码友网所有,如未经许可,禁止任何形式转载,违者必究。

上一篇: [MySQL]MySQL数据库中如何查询分组后每组中的最后一条记录?

下一篇: [LINQ].NET/C#应用程序开发中如何使用LINQ中ForEach()方法设置实体对象的多个属性的值呢?

本文永久链接码友网 » [LINQ]收集.NET/C#应用程序开发中一些好的/有用的关于LINQ的非微软官方的静态扩展方法

分享扩散:

发表评论

登录用户才能发表评论, 请 登 录 或者 注册