IEnumerableExtensions.cs 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469
  1. #nullable enable
  2. using System;
  3. using System.Collections.Generic;
  4. using System.Linq;
  5. using System.Linq.Expressions;
  6. using System.Threading;
  7. using System.Threading.Tasks;
  8. namespace Masuit.Tools
  9. {
  10. public static partial class IEnumerableExtensions
  11. {
  12. /// <summary>
  13. /// 按字段去重
  14. /// </summary>
  15. /// <typeparam name="TSource"></typeparam>
  16. /// <typeparam name="TKey"></typeparam>
  17. /// <param name="source"></param>
  18. /// <param name="keySelector"></param>
  19. /// <returns></returns>
  20. public static IEnumerable<TSource> DistinctBy<TSource, TKey>(this IEnumerable<TSource> source, Func<TSource, TKey> keySelector)
  21. {
  22. var hash = new HashSet<TKey>();
  23. return source.Where(p => hash.Add(keySelector(p)));
  24. }
  25. /// <summary>
  26. /// 添加多个元素
  27. /// </summary>
  28. /// <typeparam name="T"></typeparam>
  29. /// <param name="this"></param>
  30. /// <param name="values"></param>
  31. public static void AddRange<T>(this ICollection<T> @this, params T[] values)
  32. {
  33. foreach (var obj in values)
  34. {
  35. @this.Add(obj);
  36. }
  37. }
  38. /// <summary>
  39. /// 添加符合条件的多个元素
  40. /// </summary>
  41. /// <typeparam name="T"></typeparam>
  42. /// <param name="this"></param>
  43. /// <param name="predicate"></param>
  44. /// <param name="values"></param>
  45. public static void AddRangeIf<T>(this ICollection<T> @this, Func<T, bool> predicate, params T[] values)
  46. {
  47. foreach (var obj in values)
  48. {
  49. if (predicate(obj))
  50. {
  51. @this.Add(obj);
  52. }
  53. }
  54. }
  55. /// <summary>
  56. /// 添加不重复的元素
  57. /// </summary>
  58. /// <typeparam name="T"></typeparam>
  59. /// <param name="this"></param>
  60. /// <param name="values"></param>
  61. public static void AddRangeIfNotContains<T>(this ICollection<T> @this, params T[] values)
  62. {
  63. foreach (T obj in values)
  64. {
  65. if ([email protected](obj))
  66. {
  67. @this.Add(obj);
  68. }
  69. }
  70. }
  71. /// <summary>
  72. /// 移除符合条件的元素
  73. /// </summary>
  74. /// <typeparam name="T"></typeparam>
  75. /// <param name="this"></param>
  76. /// <param name="where"></param>
  77. public static void RemoveWhere<T>(this ICollection<T> @this, Func<T, bool> @where)
  78. {
  79. foreach (var obj in @this.Where(where).ToList())
  80. {
  81. @this.Remove(obj);
  82. }
  83. }
  84. /// <summary>
  85. /// 在元素之后添加元素
  86. /// </summary>
  87. /// <typeparam name="T"></typeparam>
  88. /// <param name="list"></param>
  89. /// <param name="condition">条件</param>
  90. /// <param name="value">值</param>
  91. public static void InsertAfter<T>(this IList<T> list, Func<T, bool> condition, T value)
  92. {
  93. foreach (var item in list.Select((item, index) => new { item, index }).Where(p => condition(p.item)).OrderByDescending(p => p.index))
  94. {
  95. if (item.index + 1 == list.Count)
  96. {
  97. list.Add(value);
  98. }
  99. else
  100. {
  101. list.Insert(item.index + 1, value);
  102. }
  103. }
  104. }
  105. /// <summary>
  106. /// 在元素之后添加元素
  107. /// </summary>
  108. /// <typeparam name="T"></typeparam>
  109. /// <param name="list"></param>
  110. /// <param name="index">索引位置</param>
  111. /// <param name="value">值</param>
  112. public static void InsertAfter<T>(this IList<T> list, int index, T value)
  113. {
  114. foreach (var item in list.Select((v, i) => new { Value = v, Index = i }).Where(p => p.Index == index).OrderByDescending(p => p.Index))
  115. {
  116. if (item.Index + 1 == list.Count)
  117. {
  118. list.Add(value);
  119. }
  120. else
  121. {
  122. list.Insert(item.Index + 1, value);
  123. }
  124. }
  125. }
  126. /// <summary>
  127. /// 转HashSet
  128. /// </summary>
  129. /// <typeparam name="T"></typeparam>
  130. /// <typeparam name="TResult"></typeparam>
  131. /// <param name="source"></param>
  132. /// <param name="selector"></param>
  133. /// <returns></returns>
  134. public static HashSet<TResult> ToHashSet<T, TResult>(this IEnumerable<T> source, Func<T, TResult> selector)
  135. {
  136. var set = new HashSet<TResult>();
  137. set.UnionWith(source.Select(selector));
  138. return set;
  139. }
  140. /// <summary>
  141. /// 遍历IEnumerable
  142. /// </summary>
  143. /// <param name="objs"></param>
  144. /// <param name="action">回调方法</param>
  145. /// <typeparam name="T"></typeparam>
  146. public static void ForEach<T>(this IEnumerable<T> objs, Action<T> action)
  147. {
  148. foreach (var o in objs)
  149. {
  150. action(o);
  151. }
  152. }
  153. /// <summary>
  154. /// 异步foreach
  155. /// </summary>
  156. /// <typeparam name="T"></typeparam>
  157. /// <param name="source"></param>
  158. /// <param name="maxParallelCount">最大并行数</param>
  159. /// <param name="action"></param>
  160. /// <param name="cancellationToken"></param>
  161. /// <returns></returns>
  162. public static async Task ForeachAsync<T>(this IEnumerable<T> source, Func<T, Task> action, int maxParallelCount, CancellationToken cancellationToken = default)
  163. {
  164. var list = new List<Task>();
  165. foreach (var item in source)
  166. {
  167. if (cancellationToken.IsCancellationRequested)
  168. {
  169. return;
  170. }
  171. list.Add(action(item));
  172. if (list.Count >= maxParallelCount)
  173. {
  174. await Task.WhenAll(list);
  175. list.Clear();
  176. }
  177. }
  178. await Task.WhenAll(list);
  179. }
  180. /// <summary>
  181. /// 异步foreach
  182. /// </summary>
  183. /// <typeparam name="T"></typeparam>
  184. /// <param name="source"></param>
  185. /// <param name="action"></param>
  186. /// <returns></returns>
  187. public static Task ForeachAsync<T>(this IEnumerable<T> source, Func<T, Task> action, CancellationToken cancellationToken = default)
  188. {
  189. return ForeachAsync(source, action, source.Count(), cancellationToken);
  190. }
  191. /// <summary>
  192. /// 异步Select
  193. /// </summary>
  194. /// <typeparam name="T"></typeparam>
  195. /// <typeparam name="TResult"></typeparam>
  196. /// <param name="source"></param>
  197. /// <param name="selector"></param>
  198. /// <returns></returns>
  199. public static Task<TResult[]> SelectAsync<T, TResult>(this IEnumerable<T> source, Func<T, Task<TResult>> selector)
  200. {
  201. return Task.WhenAll(source.Select(selector));
  202. }
  203. /// <summary>
  204. /// 异步Select
  205. /// </summary>
  206. /// <typeparam name="T"></typeparam>
  207. /// <typeparam name="TResult"></typeparam>
  208. /// <param name="source"></param>
  209. /// <param name="selector"></param>
  210. /// <returns></returns>
  211. public static Task<TResult[]> SelectAsync<T, TResult>(this IEnumerable<T> source, Func<T, int, Task<TResult>> selector)
  212. {
  213. return Task.WhenAll(source.Select(selector));
  214. }
  215. /// <summary>
  216. /// 异步For
  217. /// </summary>
  218. /// <typeparam name="T"></typeparam>
  219. /// <param name="source"></param>
  220. /// <param name="selector"></param>
  221. /// <param name="maxParallelCount">最大并行数</param>
  222. /// <param name="cancellationToken">取消口令</param>
  223. /// <returns></returns>
  224. public static async Task ForAsync<T>(this IEnumerable<T> source, Func<T, int, Task> selector, int maxParallelCount, CancellationToken cancellationToken = default)
  225. {
  226. var list = new List<Task>();
  227. int index = 0;
  228. foreach (var item in source)
  229. {
  230. if (cancellationToken.IsCancellationRequested)
  231. {
  232. return;
  233. }
  234. list.Add(selector(item, index++));
  235. if (list.Count >= maxParallelCount)
  236. {
  237. await Task.WhenAll(list);
  238. list.Clear();
  239. }
  240. }
  241. await Task.WhenAll(list);
  242. }
  243. /// <summary>
  244. /// 异步For
  245. /// </summary>
  246. /// <typeparam name="T"></typeparam>
  247. /// <param name="source"></param>
  248. /// <param name="selector"></param>
  249. /// <param name="cancellationToken">取消口令</param>
  250. /// <returns></returns>
  251. public static Task ForAsync<T>(this IEnumerable<T> source, Func<T, int, Task> selector, CancellationToken cancellationToken = default)
  252. {
  253. return ForAsync(source, selector, source.Count(), cancellationToken);
  254. }
  255. /// <summary>
  256. /// 取最大值
  257. /// </summary>
  258. /// <typeparam name="TSource"></typeparam>
  259. /// <typeparam name="TResult"></typeparam>
  260. /// <param name="source"></param>
  261. /// <param name="selector"></param>
  262. /// <returns></returns>
  263. public static TResult MaxOrDefault<TSource, TResult>(this IQueryable<TSource> source, Expression<Func<TSource, TResult>> selector) => source.Select(selector).DefaultIfEmpty().Max();
  264. /// <summary>
  265. /// 取最大值
  266. /// </summary>
  267. /// <typeparam name="TSource"></typeparam>
  268. /// <typeparam name="TResult"></typeparam>
  269. /// <param name="source"></param>
  270. /// <param name="selector"></param>
  271. /// <param name="defaultValue"></param>
  272. /// <returns></returns>
  273. public static TResult MaxOrDefault<TSource, TResult>(this IQueryable<TSource> source, Expression<Func<TSource, TResult>> selector, TResult defaultValue) => source.Select(selector).DefaultIfEmpty(defaultValue).Max();
  274. /// <summary>
  275. /// 取最大值
  276. /// </summary>
  277. /// <typeparam name="TSource"></typeparam>
  278. /// <param name="source"></param>
  279. /// <returns></returns>
  280. public static TSource MaxOrDefault<TSource>(this IQueryable<TSource> source) => source.DefaultIfEmpty().Max();
  281. /// <summary>
  282. /// 取最大值
  283. /// </summary>
  284. /// <typeparam name="TSource"></typeparam>
  285. /// <param name="source"></param>
  286. /// <param name="defaultValue"></param>
  287. /// <returns></returns>
  288. public static TSource MaxOrDefault<TSource>(this IQueryable<TSource> source, TSource defaultValue) => source.DefaultIfEmpty(defaultValue).Max();
  289. /// <summary>
  290. /// 取最大值
  291. /// </summary>
  292. /// <typeparam name="TSource"></typeparam>
  293. /// <typeparam name="TResult"></typeparam>
  294. /// <param name="source"></param>
  295. /// <param name="selector"></param>
  296. /// <param name="defaultValue"></param>
  297. /// <returns></returns>
  298. public static TResult MaxOrDefault<TSource, TResult>(this IEnumerable<TSource> source, Func<TSource, TResult> selector, TResult defaultValue) => source.Select(selector).DefaultIfEmpty(defaultValue).Max();
  299. /// <summary>
  300. /// 取最大值
  301. /// </summary>
  302. /// <typeparam name="TSource"></typeparam>
  303. /// <typeparam name="TResult"></typeparam>
  304. /// <param name="source"></param>
  305. /// <param name="selector"></param>
  306. /// <returns></returns>
  307. public static TResult MaxOrDefault<TSource, TResult>(this IEnumerable<TSource> source, Func<TSource, TResult> selector) => source.Select(selector).DefaultIfEmpty().Max();
  308. /// <summary>
  309. /// 取最大值
  310. /// </summary>
  311. /// <typeparam name="TSource"></typeparam>
  312. /// <param name="source"></param>
  313. /// <returns></returns>
  314. public static TSource MaxOrDefault<TSource>(this IEnumerable<TSource> source) => source.DefaultIfEmpty().Max();
  315. /// <summary>
  316. /// 取最大值
  317. /// </summary>
  318. /// <typeparam name="TSource"></typeparam>
  319. /// <param name="source"></param>
  320. /// <param name="defaultValue"></param>
  321. /// <returns></returns>
  322. public static TSource MaxOrDefault<TSource>(this IEnumerable<TSource> source, TSource defaultValue) => source.DefaultIfEmpty(defaultValue).Max();
  323. /// <summary>
  324. /// 取最小值
  325. /// </summary>
  326. /// <typeparam name="TSource"></typeparam>
  327. /// <typeparam name="TResult"></typeparam>
  328. /// <param name="source"></param>
  329. /// <param name="selector"></param>
  330. /// <returns></returns>
  331. public static TResult MinOrDefault<TSource, TResult>(this IQueryable<TSource> source, Expression<Func<TSource, TResult>> selector) => source.Select(selector).DefaultIfEmpty().Min();
  332. /// <summary>
  333. /// 取最小值
  334. /// </summary>
  335. /// <typeparam name="TSource"></typeparam>
  336. /// <typeparam name="TResult"></typeparam>
  337. /// <param name="source"></param>
  338. /// <param name="selector"></param>
  339. /// <param name="defaultValue"></param>
  340. /// <returns></returns>
  341. public static TResult MinOrDefault<TSource, TResult>(this IQueryable<TSource> source, Expression<Func<TSource, TResult>> selector, TResult defaultValue) => source.Select(selector).DefaultIfEmpty(defaultValue).Min();
  342. /// <summary>
  343. /// 取最小值
  344. /// </summary>
  345. /// <typeparam name="TSource"></typeparam>
  346. /// <param name="source"></param>
  347. /// <returns></returns>
  348. public static TSource MinOrDefault<TSource>(this IQueryable<TSource> source) => source.DefaultIfEmpty().Min();
  349. /// <summary>
  350. /// 取最小值
  351. /// </summary>
  352. /// <typeparam name="TSource"></typeparam>
  353. /// <param name="source"></param>
  354. /// <param name="defaultValue"></param>
  355. /// <returns></returns>
  356. public static TSource MinOrDefault<TSource>(this IQueryable<TSource> source, TSource defaultValue) => source.DefaultIfEmpty(defaultValue).Min();
  357. /// <summary>
  358. /// 取最小值
  359. /// </summary>
  360. /// <typeparam name="TSource"></typeparam>
  361. /// <typeparam name="TResult"></typeparam>
  362. /// <param name="source"></param>
  363. /// <param name="selector"></param>
  364. /// <returns></returns>
  365. public static TResult MinOrDefault<TSource, TResult>(this IEnumerable<TSource> source, Func<TSource, TResult> selector) => source.Select(selector).DefaultIfEmpty().Min();
  366. /// <summary>
  367. /// 取最小值
  368. /// </summary>
  369. /// <typeparam name="TSource"></typeparam>
  370. /// <typeparam name="TResult"></typeparam>
  371. /// <param name="source"></param>
  372. /// <param name="selector"></param>
  373. /// <param name="defaultValue"></param>
  374. /// <returns></returns>
  375. public static TResult MinOrDefault<TSource, TResult>(this IEnumerable<TSource> source, Func<TSource, TResult> selector, TResult defaultValue) => source.Select(selector).DefaultIfEmpty(defaultValue).Min();
  376. /// <summary>
  377. /// 取最小值
  378. /// </summary>
  379. /// <typeparam name="TSource"></typeparam>
  380. /// <param name="source"></param>
  381. /// <returns></returns>
  382. public static TSource MinOrDefault<TSource>(this IEnumerable<TSource> source) => source.DefaultIfEmpty().Min();
  383. /// <summary>
  384. /// 取最小值
  385. /// </summary>
  386. /// <typeparam name="TSource"></typeparam>
  387. /// <param name="source"></param>
  388. /// <param name="defaultValue"></param>
  389. /// <returns></returns>
  390. public static TSource MinOrDefault<TSource>(this IEnumerable<TSource> source, TSource defaultValue) => source.DefaultIfEmpty(defaultValue).Min();
  391. /// <summary>
  392. /// 标准差
  393. /// </summary>
  394. /// <typeparam name="T"></typeparam>
  395. /// <param name="source"></param>
  396. /// <param name="selector"></param>
  397. /// <returns></returns>
  398. public static TResult StandardDeviation<T, TResult>(this IEnumerable<T> source, Func<T, TResult> selector) where TResult : IConvertible
  399. {
  400. return StandardDeviation(source.Select(t => selector(t).ConvertTo<double>())).ConvertTo<TResult>();
  401. }
  402. /// <summary>
  403. /// 标准差
  404. /// </summary>
  405. /// <typeparam name="T"></typeparam>
  406. /// <param name="source"></param>
  407. /// <returns></returns>
  408. public static T StandardDeviation<T>(this IEnumerable<T> source) where T : IConvertible
  409. {
  410. return StandardDeviation(source.Select(t => t.ConvertTo<double>())).ConvertTo<T>();
  411. }
  412. /// <summary>
  413. /// 标准差
  414. /// </summary>
  415. /// <param name="source"></param>
  416. /// <returns></returns>
  417. public static double StandardDeviation(this IEnumerable<double> source)
  418. {
  419. double result = 0;
  420. int count = source.Count();
  421. if (count > 1)
  422. {
  423. double avg = source.Average();
  424. double sum = source.Sum(d => (d - avg) * (d - avg));
  425. result = Math.Sqrt(sum / count);
  426. }
  427. return result;
  428. }
  429. }
  430. }