/Dev3Lib/Dev3Lib/Algorithms/EnumerableAlgorithms.cs

http://dev3lib.codeplex.com · C# · 432 lines · 351 code · 81 blank · 0 comment · 76 complexity · ddda2cf73ef0900a67e7acca92796666 MD5 · raw file

  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Text;
  5. using System.Diagnostics;
  6. using System.Collections;
  7. namespace Dev3Lib.Algorithms
  8. {
  9. public static class EnumerableAlgorithms
  10. {
  11. [DebuggerStepThrough]
  12. public static void SafeForEach<T>(this IEnumerable<T> items, Action<T> action)
  13. {
  14. if (items == null)
  15. return;
  16. items.ForEach(action);
  17. }
  18. private static void ForEach<T>(this IEnumerable<T> items, Action<T> action)
  19. {
  20. var en = items.GetEnumerator();
  21. while (en.MoveNext())
  22. action(en.Current);
  23. }
  24. [DebuggerStepThrough]
  25. public static T SafeFind<T>(this IEnumerable<T> items, Predicate<T> predicate)
  26. {
  27. T item;
  28. if (items.SafeTryFind(predicate, out item))
  29. return item;
  30. else
  31. return default(T);
  32. }
  33. [DebuggerStepThrough]
  34. public static T SafeFind<T>(this IEnumerable<T> items, Predicate<T> predicate, T defaultValueIfNotFind)
  35. {
  36. T item;
  37. if (items.SafeTryFind(predicate, out item))
  38. return item;
  39. else
  40. return defaultValueIfNotFind;
  41. }
  42. [DebuggerStepThrough]
  43. public static void SafeFind<T>(this IEnumerable<T> items, Predicate<T> predicate,
  44. Action<T> actionIfFound)
  45. {
  46. T item;
  47. if (items.SafeTryFind(predicate, out item))
  48. {
  49. actionIfFound(item);
  50. }
  51. }
  52. [DebuggerStepThrough]
  53. public static bool SafeTryFind<T>(this IEnumerable<T> items, Predicate<T> predicate, out T item)
  54. {
  55. item = default(T);
  56. if (items == null)
  57. {
  58. return false;
  59. }
  60. var en = items.GetEnumerator();
  61. while (en.MoveNext())
  62. {
  63. if (predicate(en.Current))
  64. {
  65. item = en.Current;
  66. return true;
  67. }
  68. }
  69. return false;
  70. }
  71. [DebuggerStepThrough]
  72. public static List<T> SafeFindAll<T>(this IEnumerable<T> items, Predicate<T> predicate)
  73. {
  74. if (items == null)
  75. return new List<T>();
  76. return items.FindAll(predicate);
  77. }
  78. public static List<T> SafeFindAll<T>(this IEnumerable items, Predicate<T> predicate)
  79. {
  80. if (items == null)
  81. return new List<T>();
  82. var en = items.GetEnumerator();
  83. List<T> filteredItems = new List<T>();
  84. while (en.MoveNext())
  85. {
  86. if (predicate((T)en.Current))
  87. filteredItems.Add((T)en.Current);
  88. }
  89. return filteredItems;
  90. }
  91. private static List<T> FindAll<T>(this IEnumerable<T> items, Predicate<T> predicate)
  92. {
  93. var list = items as List<T>;
  94. if (list != null)
  95. return list.FindAll(predicate);
  96. var arr = items as T[];
  97. if (arr != null)
  98. return new List<T>(Array.FindAll<T>(arr, predicate));
  99. List<T> results = new List<T>();
  100. var en = items.GetEnumerator();
  101. while (en.MoveNext())
  102. {
  103. if (predicate(en.Current))
  104. results.Add(en.Current);
  105. }
  106. return results;
  107. }
  108. [DebuggerStepThrough]
  109. public static int SafeCount<T>(this IEnumerable<T> items)
  110. {
  111. if (items == null)
  112. return 0;
  113. if (items is IList)
  114. return ((IList)items).Count;
  115. if (items is T[])
  116. return ((T[])items).Length;
  117. return items.Count(null);
  118. }
  119. [DebuggerStepThrough]
  120. public static int SafeCount<T>(this IEnumerable<T> items, Predicate<T> predicate)
  121. {
  122. if (items == null)
  123. return 0;
  124. else
  125. return items.Count(predicate);
  126. }
  127. private static int Count<T>(this IEnumerable<T> items, Predicate<T> predicate)
  128. {
  129. int count = 0;
  130. if (predicate == null)
  131. {
  132. if (items is IList)
  133. return ((IList)items).Count;
  134. if (items is T[])
  135. return ((T[])items).Length;
  136. var en = items.GetEnumerator();
  137. while (en.MoveNext())
  138. count++;
  139. return count;
  140. }
  141. else
  142. {
  143. if (items is List<T>)
  144. return ((List<T>)items).FindAll(predicate).Count;
  145. if (items is T[])
  146. return Array.FindAll((T[])items, predicate).Length;
  147. var en = items.GetEnumerator();
  148. while (en.MoveNext())
  149. {
  150. if (predicate(en.Current))
  151. count++;
  152. }
  153. return count;
  154. }
  155. }
  156. [DebuggerStepThrough]
  157. public static List<OutT> SafeConvertAll<InputT, OutT>(this IEnumerable<InputT> items, Converter<InputT, OutT> converter)
  158. {
  159. if (items == null)
  160. return new List<OutT>();
  161. var items1 = items as List<InputT>;
  162. if (items1 != null)
  163. return items1.ConvertAll(n => converter(n));
  164. List<OutT> list = new List<OutT>(items.Count(null));
  165. var en = items.GetEnumerator();
  166. while (en.MoveNext())
  167. {
  168. list.Add(converter(en.Current));
  169. }
  170. return list;
  171. }
  172. [DebuggerStepThrough]
  173. public static List<OutT> SafeConvertAllItems<InputT, OutT>(this IEnumerable<InputT> items, Converter<InputT, IEnumerable<OutT>> converter)
  174. {
  175. List<OutT> list = new List<OutT>();
  176. items.SafeForEach(n => list.AddRange(converter(n).SafeToEnumerable()));
  177. return list;
  178. }
  179. [DebuggerStepThrough]
  180. public static T[] SafeToArray<T>(this IEnumerable<T> items)
  181. {
  182. if (items == null)
  183. return new T[] { };
  184. if (items is T[])
  185. return (T[])items;
  186. if (items is List<T>)
  187. return ((List<T>)items).ToArray();
  188. T[] rets = (T[])Array.CreateInstance(typeof(T), items.Count(null));
  189. int index = 0;
  190. var en = items.GetEnumerator();
  191. while (en.MoveNext())
  192. {
  193. rets[index++] = en.Current;
  194. }
  195. return rets;
  196. }
  197. [DebuggerStepThrough]
  198. public static IEnumerable<T> SafeToEnumerable<T>(this IEnumerable<T> items)
  199. {
  200. if (items == null)
  201. return new T[] { };
  202. else
  203. return items;
  204. }
  205. [DebuggerStepThrough]
  206. public static bool SafeExists<T>(this IEnumerable<T> items, Predicate<T> predicate)
  207. {
  208. T item;
  209. return items.SafeTryFind(predicate, out item);
  210. }
  211. [DebuggerStepThrough]
  212. public static bool SafeIsEqual<T>(this IEnumerable<T> source, IEnumerable<T> target)
  213. {
  214. return !(source.SafeExists(n => !target.SafeExists(m => Comparer<T>.Default.Compare(m, n) == 0))
  215. || target.SafeExists(n => !source.SafeExists(m => Comparer<T>.Default.Compare(m, n) == 0)));
  216. }
  217. [DebuggerStepThrough]
  218. public static bool SafeIsEqual<T>(this IEnumerable<T> source, IEnumerable<T> target, Func<T, T, bool> compare)
  219. {
  220. return !(source.SafeExists(n => !target.SafeExists(m => compare(m, n)))
  221. || target.SafeExists(n => !source.SafeExists(m => compare(m, n))));
  222. }
  223. [DebuggerStepThrough]
  224. public static bool IsNullOrEmpty(this IEnumerable source)
  225. {
  226. if (source == null)
  227. return true;
  228. var en = source.GetEnumerator();
  229. if (en.MoveNext())
  230. return false;
  231. else
  232. return true;
  233. }
  234. [DebuggerStepThrough]
  235. public static IEnumerable<T> SafeTake<T>(this IEnumerable<T> source, int returnCount)
  236. {
  237. if (source.IsNullOrEmpty())
  238. return new T[] { };
  239. else
  240. {
  241. List<T> list = new List<T>();
  242. int count = 0;
  243. var en = source.GetEnumerator();
  244. while (en.MoveNext())
  245. {
  246. if (count++ == returnCount)
  247. break;
  248. list.Add(en.Current);
  249. }
  250. return list;
  251. }
  252. }
  253. [DebuggerStepThrough]
  254. public static IEnumerable<T> SafeTakeFirstHalf<T>(this IEnumerable<T> source)
  255. {
  256. var count = source.SafeCount();
  257. if (count == 0)
  258. return new T[] { };
  259. if (IsOddCount(count))
  260. {
  261. return source.SafeTake(count / 2 + 1);
  262. }
  263. else
  264. {
  265. return source.SafeTake(count / 2);
  266. }
  267. }
  268. [DebuggerStepThrough]
  269. public static IEnumerable<T> SafeTakeSecondHalf<T>(this IEnumerable<T> source)
  270. {
  271. List<T> list = new List<T>(source.SafeToEnumerable());
  272. source.SafeTakeFirstHalf().SafeForEach(
  273. n => list.Remove(n)
  274. );
  275. return list;
  276. }
  277. [DebuggerStepThrough]
  278. public static bool SafeIsOddCount<T>(this IEnumerable<T> source)
  279. {
  280. return IsOddCount(source.SafeCount());
  281. }
  282. private static bool IsOddCount(int count)
  283. {
  284. decimal val = Convert.ToInt64(count);
  285. return !(Math.Round(val / 2, 0) == val / 2);
  286. }
  287. [DebuggerStepThrough]
  288. public static IEnumerable<T> SafeGetOverlapped<T>(this IEnumerable<T> source, IEnumerable<T> target, Func<T, T, bool> compare)
  289. {
  290. if (source.IsNullOrEmpty() || target.IsNullOrEmpty())
  291. return new T[] { };
  292. return source.SafeFindAll(n => target.SafeExists(m => compare(n, m)));
  293. }
  294. [DebuggerStepThrough]
  295. public static bool IsNullOrEmpty<T>(this IEnumerable<T> source)
  296. {
  297. if (source == null)
  298. return true;
  299. return !source.GetEnumerator().MoveNext();
  300. }
  301. public static int GetPosition<T>(this IEnumerable<T> source, T obj) where T : class
  302. {
  303. int i = 0;
  304. var en = source.GetEnumerator();
  305. while (en.MoveNext())
  306. {
  307. if (Object.ReferenceEquals(en.Current, obj))
  308. return i;
  309. else
  310. i++;
  311. }
  312. throw new PostionNotFoundException();
  313. }
  314. public static T SafeLastOrDefault<T>(this IEnumerable<T> items)
  315. {
  316. if (items.IsNullOrEmpty())
  317. return default(T);
  318. {
  319. var list = items as IList<T>;
  320. if (list != null)
  321. return list[list.Count - 1];
  322. }
  323. {
  324. var list = items as IList;
  325. if (list != null)
  326. return (T)list[list.Count - 1];
  327. }
  328. var en = items.GetEnumerator();
  329. T last = default(T);
  330. while (en.MoveNext())
  331. last = en.Current;
  332. return last;
  333. }
  334. public static void SafeForeach(this IEnumerable items, Action<object> action)
  335. {
  336. foreach (var obj in items)
  337. {
  338. action(obj);
  339. }
  340. }
  341. public static List<T> SafeConvertAll<T>(this IEnumerable items, Func<object, T> func)
  342. {
  343. List<T> itemList = new List<T>();
  344. foreach (var obj in items)
  345. {
  346. itemList.Add(func(obj));
  347. }
  348. return itemList;
  349. }
  350. }
  351. }