123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126 |
- using System;
- using System.Collections;
- using System.Collections.Concurrent;
- using System.Collections.Generic;
- namespace VCommon.Collections
- {
- public static class EnumerableExtensionMethod
- {
- /// <summary> 按提供的条件以及变换方法叠加序列 </summary>
- /// <typeparam name="TInput">序列元素类型</typeparam>
- /// <typeparam name="TStackedGroup">分组类型</typeparam>
- /// <param name="sequence">序列</param>
- /// <param name="groupingCondition">叠加条件</param>
- /// <param name="createStackGroup">分组创建方法,提供当前元素</param>
- /// <param name="addToGroup">分组叠加方法,提供分组和当前元素</param>
- public static TStackedGroup[] Stack<TInput, TStackedGroup>(this IEnumerable<TInput> sequence, Func<TInput, bool> groupingCondition, Func<TInput, TStackedGroup> createStackGroup, Action<TStackedGroup, TInput> addToGroup) where TStackedGroup : class
- {
- var list = new List<TStackedGroup>();
- TStackedGroup lasStackedGroup = null;
- foreach (var item in sequence)
- {
- var toGroup = groupingCondition(item);
- if (null != lasStackedGroup && toGroup)
- {
- addToGroup(lasStackedGroup, item);
- }
- else if (toGroup)
- {
- lasStackedGroup = createStackGroup(item);
- list.Add(lasStackedGroup);
- }
- else
- {
- lasStackedGroup = null;
- list.Add(createStackGroup(item));
- }
- }
- return list.ToArray();
- }
- /// <summary>
- /// 将序列中连续且符合条件的元素,保留第一个其余移除
- /// </summary>
- /// <typeparam name="T">序列元素类型</typeparam>
- /// <param name="sequence">序列</param>
- /// <param name="stackCondition">移除条件</param>
- public static T[] StackSequence<T>(this IEnumerable<T> sequence, Func<T, bool> stackCondition) where T : class
- {
- return sequence.Stack(stackCondition, p => p, (a, b) => { });
- }
- public class Group<TKey, TElement>
- {
- private readonly List<TElement> _elements = new List<TElement>();
- public TElement[] Elements => _elements.ToArray();
- public Group(TKey key) => Key = key;
- public void Add(TElement element) => _elements.Add(element);
- public TKey Key { get; }
- }
- public static Group<TKey, TElement>[] GroupContiguous<TElement, TKey>(this TElement[] sequence, Func<TElement, TKey> keySelector) => GroupContiguous(sequence, keySelector, EqualityComparer<TKey>.Default);
- public static Group<TKey, TElement>[] GroupContiguous<TElement, TKey>(this TElement[] sequence, Func<TElement, TKey> keySelector, IEqualityComparer<TKey> comparer)
- {
- var result = new List<Group<TKey, TElement>>();
- Group<TKey, TElement> group = null;
- foreach (var element in sequence)
- {
- var key = keySelector(element);
- if (null == group || false == comparer.Equals(group.Key, key))
- {
- group = new Group<TKey, TElement>(key);
- result.Add(group);
- group.Add(element);
- }
- else
- {
- group.Add(element);
- }
- }
- return result.ToArray();
- }
- /// <summary> 包裹泛型IEnumerable实例, 避免可能的数组实例造成EF动态过滤失败 </summary>
- public static IEnumerable<T> WrapEnumerable<T>(this IEnumerable<T> source) => new EnumerableWrapper<T>(source);
- private class EnumerableWrapper<T> : IEnumerable<T>
- {
- private readonly IEnumerable<T> _underlyingInstance;
- public EnumerableWrapper(IEnumerable<T> underlyingInstance) => _underlyingInstance = underlyingInstance;
- IEnumerator<T> IEnumerable<T>.GetEnumerator() => _underlyingInstance.GetEnumerator();
- IEnumerator IEnumerable.GetEnumerator() => _underlyingInstance.GetEnumerator();
- }
- //public static HashSet<T> ToHashSet<T>(this IEnumerable<T> source) => new HashSet<T>(source);
- public static ConcurrentDictionary<TKey, TElement> ToConcurrentDictionary<TSource, TKey, TElement>(this IEnumerable<TSource> source, Func<TSource, TKey> keySelector, Func<TSource, TElement> elementSelector, IEqualityComparer<TKey> comparer = null)
- {
- //REF: stackoverflow.com/a/27064366/2430943 with MODIFY
- if (source == null) throw new ArgumentNullException(nameof(source));
- if (keySelector == null) throw new ArgumentNullException(nameof(keySelector));
- if (elementSelector == null) throw new ArgumentNullException(nameof(elementSelector));
- var d = comparer == null
- ? new ConcurrentDictionary<TKey, TElement>()
- : new ConcurrentDictionary<TKey, TElement>(comparer);
- foreach (var element in source)
- if (false == d.TryAdd(keySelector(element), elementSelector(element)))
- throw new ArgumentException("KeyDuplicated");
- return d;
- }
- }
- }
|