Browse Source

增加ExceptBy,IntersectBy扩展函数
改进对比两个集合哪些是新增的、删除的、修改的函数

懒得勤快 4 years ago
parent
commit
7e69a82128

+ 146 - 13
Masuit.Tools.Abstractions/Extensions/BaseType/IEnumerableExtensions.cs

@@ -13,6 +13,34 @@ namespace Masuit.Tools
 {
     public static partial class IEnumerableExtensions
     {
+        /// <summary>
+        /// 按字段属性判等取交集
+        /// </summary>
+        /// <typeparam name="TFirst"></typeparam>
+        /// <typeparam name="TSecond"></typeparam>
+        /// <param name="second"></param>
+        /// <param name="condition"></param>
+        /// <param name="first"></param>
+        /// <returns></returns>
+        public static IEnumerable<TFirst> IntersectBy<TFirst, TSecond>(this IEnumerable<TFirst> first, IEnumerable<TSecond> second, Func<TFirst, TSecond, bool> condition)
+        {
+            return first.Where(f => second.Any(s => condition(f, s)));
+        }
+
+        /// <summary>
+        /// 按字段属性判等取差集
+        /// </summary>
+        /// <typeparam name="TFirst"></typeparam>
+        /// <typeparam name="TSecond"></typeparam>
+        /// <param name="second"></param>
+        /// <param name="condition"></param>
+        /// <param name="first"></param>
+        /// <returns></returns>
+        public static IEnumerable<TFirst> ExceptBy<TFirst, TSecond>(this IEnumerable<TFirst> first, IEnumerable<TSecond> second, Func<TFirst, TSecond, bool> condition)
+        {
+            return first.Where(f => !second.Any(s => condition(f, s)));
+        }
+
 #if NET6_0
 #else
 
@@ -30,6 +58,96 @@ namespace Masuit.Tools
             return source.Where(p => hash.Add(keySelector(p)));
         }
 
+        /// <summary>
+        /// 按字段属性判等取交集
+        /// </summary>
+        /// <typeparam name="TSource"></typeparam>
+        /// <typeparam name="TKey"></typeparam>
+        /// <param name="first"></param>
+        /// <param name="second"></param>
+        /// <param name="keySelector"></param>
+        /// <returns></returns>
+        public static IEnumerable<TSource> IntersectBy<TSource, TKey>(this IEnumerable<TSource> first, IEnumerable<TKey> second, Func<TSource, TKey> keySelector)
+        {
+            return first.IntersectBy(second, keySelector, null);
+        }
+
+        /// <summary>
+        /// 按字段属性判等取交集
+        /// </summary>
+        /// <typeparam name="TSource"></typeparam>
+        /// <typeparam name="TKey"></typeparam>
+        /// <param name="first"></param>
+        /// <param name="second"></param>
+        /// <param name="keySelector"></param>
+        /// <returns></returns>
+        public static IEnumerable<TSource> IntersectBy<TSource, TKey>(this IEnumerable<TSource> first, IEnumerable<TKey> second, Func<TSource, TKey> keySelector, IEqualityComparer<TKey>? comparer)
+        {
+            if (first == null)
+                throw new ArgumentNullException(nameof(first));
+            if (second == null)
+                throw new ArgumentNullException(nameof(second));
+            if (keySelector == null)
+                throw new ArgumentNullException(nameof(keySelector));
+            return IntersectByIterator(first, second, keySelector, comparer);
+        }
+
+        private static IEnumerable<TSource> IntersectByIterator<TSource, TKey>(IEnumerable<TSource> first, IEnumerable<TKey> second, Func<TSource, TKey> keySelector, IEqualityComparer<TKey> comparer)
+        {
+            var set = new HashSet<TKey>(second, comparer);
+            foreach (var source in first)
+            {
+                if (set.Remove(keySelector(source)))
+                    yield return source;
+            }
+        }
+
+        /// <summary>
+        /// 按字段属性判等取差集
+        /// </summary>
+        /// <typeparam name="TSource"></typeparam>
+        /// <typeparam name="TKey"></typeparam>
+        /// <param name="first"></param>
+        /// <param name="second"></param>
+        /// <param name="keySelector"></param>
+        /// <returns></returns>
+        public static IEnumerable<TSource> ExceptBy<TSource, TKey>(this IEnumerable<TSource> first, IEnumerable<TKey> second, Func<TSource, TKey> keySelector)
+        {
+            return first.ExceptBy(second, keySelector, null);
+        }
+
+        /// <summary>
+        /// 按字段属性判等取差集
+        /// </summary>
+        /// <typeparam name="TSource"></typeparam>
+        /// <typeparam name="TKey"></typeparam>
+        /// <param name="first"></param>
+        /// <param name="second"></param>
+        /// <param name="keySelector"></param>
+        /// <param name="comparer"></param>
+        /// <returns></returns>
+        /// <exception cref="ArgumentNullException"></exception>
+        public static IEnumerable<TSource> ExceptBy<TSource, TKey>(this IEnumerable<TSource> first, IEnumerable<TKey> second, Func<TSource, TKey> keySelector, IEqualityComparer<TKey>? comparer)
+        {
+            if (first == null)
+                throw new ArgumentNullException(nameof(first));
+            if (second == null)
+                throw new ArgumentNullException(nameof(second));
+            if (keySelector == null)
+                throw new ArgumentNullException(nameof(keySelector));
+            return ExceptByIterator(first, second, keySelector, comparer);
+        }
+
+        private static IEnumerable<TSource> ExceptByIterator<TSource, TKey>(IEnumerable<TSource> first, IEnumerable<TKey> second, Func<TSource, TKey> keySelector, IEqualityComparer<TKey> comparer)
+        {
+            var set = new HashSet<TKey>(second, comparer);
+            foreach (var source in first)
+            {
+                if (set.Add(keySelector(source)))
+                    yield return source;
+            }
+        }
+
 #endif
 
         /// <summary>
@@ -168,7 +286,11 @@ namespace Masuit.Tools
         /// <param name="value">值</param>
         public static void InsertAfter<T>(this IList<T> list, Func<T, bool> condition, T value)
         {
-            foreach (var item in list.Select((item, index) => new { item, index }).Where(p => condition(p.item)).OrderByDescending(p => p.index))
+            foreach (var item in list.Select((item, index) => new
+            {
+                item,
+                index
+            }).Where(p => condition(p.item)).OrderByDescending(p => p.index))
             {
                 if (item.index + 1 == list.Count)
                 {
@@ -190,7 +312,11 @@ namespace Masuit.Tools
         /// <param name="value">值</param>
         public static void InsertAfter<T>(this IList<T> list, int index, T value)
         {
-            foreach (var item in list.Select((v, i) => new { Value = v, Index = i }).Where(p => p.Index == index).OrderByDescending(p => p.Index))
+            foreach (var item in list.Select((v, i) => new
+            {
+                Value = v,
+                Index = i
+            }).Where(p => p.Index == index).OrderByDescending(p => p.Index))
             {
                 if (item.Index + 1 == list.Count)
                 {
@@ -598,6 +724,7 @@ namespace Masuit.Tools
                             return false;
                         }
                     }
+
                     return true;
                 }
             }
@@ -643,6 +770,7 @@ namespace Masuit.Tools
                             return false;
                         }
                     }
+
                     return true;
                 }
             }
@@ -665,27 +793,32 @@ namespace Masuit.Tools
         /// </summary>
         /// <typeparam name="T1"></typeparam>
         /// <typeparam name="T2"></typeparam>
-        /// <param name="olds"></param>
-        /// <param name="news"></param>
-        /// <param name="key1Selector">对比因素属性</param>
-        /// <param name="key2Selector">对比因素属性</param>
+        /// <param name="first"></param>
+        /// <param name="second"></param>
+        /// <param name="condition">对比因素条件</param>
         /// <returns></returns>
-        public static (List<T2> adds, List<T1> remove, List<T1> updates) CompareChanges<T1, T2>(this IEnumerable<T1> olds, IEnumerable<T2> news, Func<T1, object> key1Selector, Func<T2, object> key2Selector)
+        public static (List<T1> adds, List<T2> remove, List<T1> updates) CompareChanges<T1, T2>(this IEnumerable<T1> first, IEnumerable<T2> second, Func<T1, T2, bool> condition)
         {
-            return (news.Where(c => olds.All(m => key1Selector(m) != key2Selector(c))).ToList(), olds.Where(m => news.All(c => key2Selector(c) != key1Selector(m))).ToList(), olds.Where(m => news.Any(c => key1Selector(m) == key2Selector(c))).ToList());
+            var add = first.ExceptBy(second, condition).ToList();
+            var remove = second.ExceptBy(first, (s, f) => condition(f, s)).ToList();
+            var update = first.IntersectBy(second, condition).ToList();
+            return (add, remove, update);
         }
 
         /// <summary>
         /// 对比两个集合哪些是新增的、删除的、修改的
         /// </summary>
         /// <typeparam name="T"></typeparam>
-        /// <param name="olds"></param>
-        /// <param name="news"></param>
-        /// <param name="keySelector">对比因素属性</param>
+        /// <param name="first"></param>
+        /// <param name="second"></param>
+        /// <param name="condition">对比因素条件</param>
         /// <returns></returns>
-        public static (List<T> adds, List<T> remove, List<T> updates) CompareChanges<T>(this IEnumerable<T> olds, IEnumerable<T> news, Func<T, object> keySelector)
+        public static (List<T> adds, List<T> remove, List<T> updates) CompareChanges<T>(this IEnumerable<T> first, IEnumerable<T> second, Func<T, T, bool> condition)
         {
-            return (news.Where(c => olds.All(m => keySelector(m) != keySelector(c))).ToList(), olds.Where(m => news.All(c => keySelector(c) != keySelector(m))).ToList(), olds.Where(m => news.Any(c => keySelector(m) == keySelector(c))).ToList());
+            var add = first.ExceptBy(second, condition).ToList();
+            var remove = second.ExceptBy(first, (s, f) => condition(f, s)).ToList();
+            var update = first.IntersectBy(second, condition).ToList();
+            return (add, remove, update);
         }
     }
 }

+ 1 - 1
Masuit.Tools.Abstractions/Masuit.Tools.Abstractions.csproj

@@ -4,7 +4,7 @@
     <LangVersion>latest</LangVersion>
     <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
     <CodeAnalysisRuleSet />
-    <Version>2.4.6.1</Version>
+    <Version>2.4.6.2</Version>
     <Authors>懒得勤快</Authors>
     <Description>Masuit.Tools基础公共库,包含一些常用的操作类,大都是静态类,加密解密,反射操作,Excel简单导出,权重随机筛选算法,分布式短id,表达式树,linq扩展,文件压缩,多线程下载和FTP客户端,硬件信息,字符串扩展方法,日期时间扩展操作,中国农历,大文件拷贝,图像裁剪,验证码,断点续传,集合扩展等常用封装。</Description>
     <Copyright>懒得勤快,长空X</Copyright>

+ 1 - 1
Masuit.Tools.Core/Masuit.Tools.Core.csproj

@@ -18,7 +18,7 @@ github:https://github.com/ldqk/Masuit.Tools
         <UserSecretsId>830c282f-f7c1-42be-8651-4cd06ac8e73f</UserSecretsId>
         <RepositoryType>Github</RepositoryType>
         <GeneratePackageOnBuild>True</GeneratePackageOnBuild>
-        <Version>2.4.6.1</Version>
+        <Version>2.4.6.2</Version>
         <FileVersion>2.4.5.6</FileVersion>
         <Company>masuit.com</Company>
         <AssemblyVersion>2.4.5.6</AssemblyVersion>

+ 1 - 1
Masuit.Tools.Net45/package.nuspec

@@ -4,7 +4,7 @@
     <!--*-->
     <id>Masuit.Tools.Net45</id>
     <!--*-->
-    <version>2.4.6.1</version>
+    <version>2.4.6.2</version>
     <title>Masuit.Tools</title>
     <!--*-->
     <authors>懒得勤快</authors>

+ 1 - 1
Masuit.Tools/package.nuspec

@@ -4,7 +4,7 @@
     <!--*-->
     <id>Masuit.Tools.Net</id>
     <!--*-->
-    <version>2.4.6.1</version>
+    <version>2.4.6.2</version>
     <title>Masuit.Tools</title>
     <!--*-->
     <authors>懒得勤快</authors>

+ 14 - 0
NetCoreTest/Program.cs

@@ -96,6 +96,20 @@ namespace NetCoreTest
                 .UseStartup<Startup>();
     }
 
+    public class ClassCmd
+    {
+        public string MyProperty { get; set; }
+
+        public int Num { get; set; }
+    }
+
+    public class ClassDto
+    {
+        public string MyProperty { get; set; }
+
+        public int Num { get; set; }
+    }
+
     public class MyClass : ITree<MyClass>
     {
         [Description("test")]