Ver Fonte

impr: 优化 Enumberable 扩展

龙腾猫跃 há 6 meses atrás
pai
commit
fcc71318a8
1 ficheiros alterados com 96 adições e 91 exclusões
  1. 96 91
      Extensions/Enumerable.cs

+ 96 - 91
Extensions/Enumerable.cs

@@ -1,142 +1,147 @@
 using System;
 using System.Collections.Generic;
+using System.Linq;
 
 namespace MeloongCore.Extensions {
     public static class EnumerableExtensions {
 
-        /// <summary>
-        /// 去重。
-        /// </summary>
-        public static List<T> Distinct<T>(this IList<T> Arr, Func<T, T, bool> IsEqual) {
-            var ResultArray = new List<T>();
-            for (int i = 0; i <= Arr.Count - 1; i++) {
-                for (int ii = i + 1; ii <= Arr.Count - 1; ii++) {
-                    if (IsEqual(Arr[i], Arr[ii])) { goto NextElement; }
-                }
-                ResultArray.Add(Arr[i]);
-NextElement:;
-            }
-            return ResultArray;
-        }
+        #region 去重
 
         /// <summary>
-        /// 判断这是否是仅有一个元素的集合。
+        /// 通过比较器进行去重。
+        /// 该方法的效率较低,建议仅在小型列表上使用,或换用 DistinctBy。
         /// </summary>
-        public static bool IsSingle<T>(this IEnumerable<T> Source) {
-            if (Source == null) {
-                return false;
-            } else if (Source is IList<T> list) {
-                return list.Count == 1;
-            } else {
-                using (var Enumerator = Source.GetEnumerator()) {
-                    if (!Enumerator.MoveNext()) { return false; }
-                    if (Enumerator.MoveNext()) { return false; }
-                    return true;
-                }
+        public static IEnumerable<T> Distinct<T>(this IList<T> list, Func<T, T, bool> comparer) {
+            for (int i = 0; i < list.Count; i++) {
+                if (!list.Skip(i + 1).Any(item => comparer(list[i], item))) yield return list[i];
             }
         }
-
         /// <summary>
-        /// 对集合的每个元素执行指定操作。
+        /// 按对象的指定值去重。
         /// </summary>
-        public static IEnumerable<T> ForEach<T>(this IEnumerable<T> Collection, Action<T> Action) {
-            foreach (T Item in Collection) {
-                Action(Item);
+        public static IEnumerable<T> DistinctBy<T, TKey>(this IEnumerable<T> source, Func<T, TKey> selector) {
+            var seen = new HashSet<TKey>();
+            foreach (var element in source) {
+                if (seen.Add(selector(element))) yield return element;
             }
-            return Collection;
         }
 
+        #endregion
+
+        #region 取最大、最小值
+
         /// <summary>
         /// 选择所有最大值对应的对象。
         /// 若没有元素则返回空列表。
         /// </summary>
-        public static List<T> MaxByAll<T, C>(this IEnumerable<T> Source, Func<T, C> Selector) where C : IComparable<C> {
-            var Results = new List<T>();
-            using (var Enumerator = Source.GetEnumerator()) {
-                if (!Enumerator.MoveNext()) { return Results; }
-                T MaxItem = Enumerator.Current;
-                C MaxValue = Selector(MaxItem);
-                Results.Add(MaxItem);
-                while (Enumerator.MoveNext()) {
-                    T CurrentItem = Enumerator.Current;
-                    C CurrentValue = Selector(CurrentItem);
-                    int Comparison = CurrentValue.CompareTo(MaxValue);
-                    if (Comparison > 0) {
-                        MaxValue = CurrentValue;
-                        Results.Clear();
-                        Results.Add(CurrentItem);
-                    } else if (Comparison == 0) {
-                        Results.Add(CurrentItem);
+        public static List<T> MaxByAll<T, C>(this IEnumerable<T> source, Func<T, C> selector) where C : IComparable<C> {
+            var results = new List<T>();
+            using (var enumerator = source.GetEnumerator()) {
+                if (!enumerator.MoveNext()) return results;
+                T maxItem = enumerator.Current;
+                C maxValue = selector(maxItem);
+                results.Add(maxItem);
+                while (enumerator.MoveNext()) {
+                    T currentItem = enumerator.Current;
+                    C currentValue = selector(currentItem);
+                    int comparisonResult = currentValue.CompareTo(maxValue);
+                    if (comparisonResult > 0) {
+                        maxValue = currentValue;
+                        results.Clear();
+                        results.Add(currentItem);
+                    } else if (comparisonResult == 0) {
+                        results.Add(currentItem);
                     }
                 }
             }
-            return Results;
+            return results;
         }
-
         /// <summary>
         /// 选择所有最小值对应的对象。
         /// 若没有元素则返回空列表。
         /// </summary>
-        public static List<T> MinByAll<T, C>(this IEnumerable<T> List, Func<T, C> Selector) where C : IComparable<C> {
-            var Results = new List<T>();
-            using (var Enumerator = List.GetEnumerator()) {
-                if (!Enumerator.MoveNext()) { return Results; }
-                T MinItem = Enumerator.Current;
-                C MinValue = Selector(MinItem);
-                Results.Add(MinItem);
-                while (Enumerator.MoveNext()) {
-                    T CurrentItem = Enumerator.Current;
-                    C CurrentValue = Selector(CurrentItem);
-                    int Comparison = CurrentValue.CompareTo(MinValue);
-                    if (Comparison < 0) {
-                        MinValue = CurrentValue;
-                        Results.Clear();
-                        Results.Add(CurrentItem);
-                    } else if (Comparison == 0) {
-                        Results.Add(CurrentItem);
+        public static List<T> MinByAll<T, C>(this IEnumerable<T> source, Func<T, C> selector) where C : IComparable<C> {
+            var results = new List<T>();
+            using (var enumerator = source.GetEnumerator()) {
+                if (!enumerator.MoveNext()) return results;
+                T minItem = enumerator.Current;
+                C minValue = selector(minItem);
+                results.Add(minItem);
+                while (enumerator.MoveNext()) {
+                    T currentItem = enumerator.Current;
+                    C currentValue = selector(currentItem);
+                    int comparisonResult = currentValue.CompareTo(minValue);
+                    if (comparisonResult < 0) {
+                        minValue = currentValue;
+                        results.Clear();
+                        results.Add(currentItem);
+                    } else if (comparisonResult == 0) {
+                        results.Add(currentItem);
                     }
                 }
             }
-            return Results;
+            return results;
         }
 
         /// <summary>
         /// 选择最大值对应的对象。
         /// 若没有元素则返回 Nothing。
         /// </summary>
-        public static T MaxBy<T, C>(this IEnumerable<T> Source, Func<T, C> Selector) where C : IComparable<C> {
-            using (var Enumerator = Source.GetEnumerator()) {
-                if (!Enumerator.MoveNext()) { return default(T); }
-                T MaxItem = Enumerator.Current;
-                C MaxValue = Selector(MaxItem);
-                while (Enumerator.MoveNext()) {
-                    C Value = Selector(Enumerator.Current);
-                    if (Value.CompareTo(MaxValue) <= 0) { continue; }
-                    MaxItem = Enumerator.Current;
-                    MaxValue = Value;
+        public static T MaxBy<T, C>(this IEnumerable<T> source, Func<T, C> selector) where C : IComparable<C> {
+            using (var enumerator = source.GetEnumerator()) {
+                if (!enumerator.MoveNext()) return default;
+                T maxItem = enumerator.Current;
+                C maxValue = selector(maxItem);
+                while (enumerator.MoveNext()) {
+                    C value = selector(enumerator.Current);
+                    if (value.CompareTo(maxValue) <= 0) continue;
+                    maxItem = enumerator.Current;
+                    maxValue = value;
                 }
-                return MaxItem;
+                return maxItem;
             }
         }
-
         /// <summary>
         /// 选择最小值对应的对象。
         /// 若没有元素则返回 Nothing。
         /// </summary>
         public static T MinBy<T, C>(this IEnumerable<T> List, Func<T, C> Selector) where C : IComparable<C> {
-            using (var Enumerator = List.GetEnumerator()) {
-                if (!Enumerator.MoveNext()) { return default; }
-                T MinItem = Enumerator.Current;
-                C MinValue = Selector(MinItem);
-                while (Enumerator.MoveNext()) {
-                    C Value = Selector(Enumerator.Current);
-                    if (Value.CompareTo(MinValue) >= 0) { continue; }
-                    MinItem = Enumerator.Current;
-                    MinValue = Value;
+            using (var enumerator = List.GetEnumerator()) {
+                if (!enumerator.MoveNext()) { return default; }
+                T minItem = enumerator.Current;
+                C minValue = Selector(minItem);
+                while (enumerator.MoveNext()) {
+                    C value = Selector(enumerator.Current);
+                    if (value.CompareTo(minValue) >= 0) { continue; }
+                    minItem = enumerator.Current;
+                    minValue = value;
                 }
-                return MinItem;
+                return minItem;
             }
         }
 
+        #endregion
+
+        /// <summary>
+        /// 判断集合是否有且仅有一个元素。
+        /// </summary>
+        public static bool IsSingle<T>(this IEnumerable<T> source) {
+            if (source == null) return false;
+            if (source is IList<T> list) return list.Count == 1;
+            using (var enumerator = source.GetEnumerator()) {
+                if (!enumerator.MoveNext()) return false;
+                if (enumerator.MoveNext()) return false;
+                return true;
+            }
+        }
+
+        /// <summary>
+        /// 对集合的每个元素执行指定操作。
+        /// </summary>
+        public static IEnumerable<T> ForEach<T>(this IEnumerable<T> source, Action<T> action) {
+            foreach (T item in source) action(item);
+            return source;
+        }
+
     }
 }