| using System; |
| using System; |
| using System.Collections.Generic; |
| using System.Collections.Generic; |
| using System.Collections.ObjectModel; |
| using System.Collections.ObjectModel; |
| using System.Linq; |
| using System.Linq; |
| using System.Text; |
| using System.Text; |
| using System.Threading.Tasks; |
| using System.Threading.Tasks; |
| |
| |
| namespace System.Collections.Generic |
| namespace System.Collections.Generic |
| { |
| { |
| /// <summary> |
| /// <summary> |
| /// Represents class with various extension methods for IEnumerable lists. |
| /// Represents class with various extension methods for IEnumerable lists. |
| /// </summary> |
| /// </summary> |
| public static class ListExtensions |
| public static class ListExtensions |
| { |
| { |
| /// <summary> |
| /// <summary> |
| /// Converts collection to <see cref="ObservableCollection{T}"/> collection. |
| /// Converts collection to <see cref="ObservableCollection{T}"/> collection. |
| /// </summary> |
| /// </summary> |
| /// <typeparam name="T"></typeparam> |
| /// <typeparam name="T"></typeparam> |
| /// <param name="source"></param> |
| /// <param name="source"></param> |
| /// <returns></returns> |
| /// <returns></returns> |
| public static ObservableCollection<T> ToObservable<T>(this IEnumerable<T> source) |
| public static ObservableCollection<T> ToObservable<T>(this IEnumerable<T> source) |
| { |
| { |
| if (source == null) |
| if (source == null) |
| { |
| { |
| return null; |
| return null; |
| } |
| } |
| |
| |
| return new ObservableCollection<T>(source); |
| return new ObservableCollection<T>(source); |
| } |
| } |
| |
| |
| /// <summary> |
| /// <summary> |
| /// Check if collection has any items. |
| /// Check if collection has any items. |
| /// </summary> |
| /// </summary> |
| /// <typeparam name="T"></typeparam> |
| /// <typeparam name="T"></typeparam> |
| /// <param name="source"></param> |
| /// <param name="source"></param> |
| /// <returns></returns> |
| /// <returns></returns> |
| public static bool HasItems<T>(this IEnumerable<T> source) |
| public static bool HasItems<T>(this IEnumerable<T> source) |
| { |
| { |
| return source?.Any() == true; |
| return source?.Any() == true; |
| } |
| } |
| |
| |
| /// <summary> |
| /// <summary> |
| /// Check if collection has any items. |
| /// Check if collection has any items. |
| /// </summary> |
| /// </summary> |
| /// <typeparam name="T"></typeparam> |
| /// <typeparam name="T"></typeparam> |
| /// <param name="source"></param> |
| /// <param name="source"></param> |
| /// <param name="predicate"></param> |
| /// <param name="predicate"></param> |
| /// <returns></returns> |
| /// <returns></returns> |
| public static bool HasItems<T>(this IEnumerable<T> source, Func<T, bool> predicate) |
| public static bool HasItems<T>(this IEnumerable<T> source, Func<T, bool> predicate) |
| { |
| { |
| return source?.Any(predicate) == true; |
| return source?.Any(predicate) == true; |
| } |
| } |
| |
| |
| /// <summary> |
| /// <summary> |
| /// Adds new item to the list only if it's not already part of the list. |
| /// Adds new item to the list only if it's not already part of the list. |
| /// </summary> |
| /// </summary> |
| /// <typeparam name="T"></typeparam> |
| /// <typeparam name="T"></typeparam> |
| /// <param name="source"></param> |
| /// <param name="source"></param> |
| /// <param name="item"></param> |
| /// <param name="item"></param> |
| /// <returns>True if item was added, false if it's already part of the list.</returns> |
| /// <returns>True if item was added, false if it's already part of the list.</returns> |
| public static bool AddMissing<T>(this IList<T> source, T item) |
| public static bool AddMissing<T>(this IList<T> source, T item) |
| { |
| { |
| if (!source.Contains(item)) |
| if (!source.Contains(item)) |
| { |
| { |
| source.Add(item); |
| source.Add(item); |
| return true; |
| return true; |
| } |
| } |
| else |
| else |
| { |
| { |
| return false; |
| return false; |
| } |
| } |
| } |
| } |
| |
| |
| /// <summary> |
| /// <summary> |
| /// Adds new items to the list only if they are not already part of the list. |
| /// Adds new items to the list only if they are not already part of the list. |
| /// </summary> |
| /// </summary> |
| /// <typeparam name="T"></typeparam> |
| /// <typeparam name="T"></typeparam> |
| /// <param name="source"></param> |
| /// <param name="source"></param> |
| /// <param name="items"></param> |
| /// <param name="items"></param> |
| /// <returns>True if an item was added, false if none item was added.</returns> |
| /// <returns>True if an item was added, false if none item was added.</returns> |
| public static bool AddMissing<T>(this IList<T> source, IEnumerable<T> items) |
| public static bool AddMissing<T>(this IList<T> source, IEnumerable<T> items) |
| { |
| { |
| if (!items.HasItems()) |
| if (!items.HasItems()) |
| { |
| { |
| return false; |
| return false; |
| } |
| } |
| |
| |
| var anyAdded = false; |
| var anyAdded = false; |
| foreach (var item in items) |
| foreach (var item in items) |
| { |
| { |
| if (AddMissing(source, item)) |
| if (AddMissing(source, item)) |
| { |
| { |
| anyAdded = true; |
| anyAdded = true; |
| } |
| } |
| } |
| } |
| |
| |
| return anyAdded; |
| return anyAdded; |
| } |
| } |
| |
| |
| /// <summary> |
| /// <summary> |
| /// Checks if collection has any non-empty string items. |
| /// Checks if collection has any non-empty string items. |
| /// </summary> |
| /// </summary> |
| /// <param name="source"></param> |
| /// <param name="source"></param> |
| /// <returns></returns> |
| /// <returns></returns> |
| public static bool HasNonEmptyItems(this IEnumerable<string> source) |
| public static bool HasNonEmptyItems(this IEnumerable<string> source) |
| { |
| { |
| return source?.Any(a => !string.IsNullOrEmpty(a)) == true; |
| return source?.Any(a => !string.IsNullOrEmpty(a)) == true; |
| } |
| } |
| |
| |
| /// <summary> |
| /// <summary> |
| /// Checks if source collection contains any items from target one, even if just partially. |
| /// Checks if source collection contains any items from target one, even if just partially. |
| /// </summary> |
| /// </summary> |
| /// <param name="source"></param> |
| /// <param name="source"></param> |
| /// <param name="target"></param> |
| /// <param name="target"></param> |
| /// <param name="comparison"></param> |
| /// <param name="comparison"></param> |
| /// <returns>True of target collection contains items that are also part of source collection.</returns> |
| /// <returns>True of target collection contains items that are also part of source collection.</returns> |
| public static bool IntersectsPartiallyWith(this IEnumerable<string> source, IEnumerable<string> target, StringComparison comparison = StringComparison.InvariantCultureIgnoreCase) |
| public static bool IntersectsPartiallyWith(this IEnumerable<string> source, IEnumerable<string> target, StringComparison comparison = StringComparison.InvariantCultureIgnoreCase) |
| { |
| { |
| if (source == null && target == null) |
| if (source == null && target == null) |
| { |
| { |
| return false; |
| return false; |
| } |
| } |
| |
| |
| if ((source == null && target != null) || (source != null && target == null)) |
| if ((source == null && target != null) || (source != null && target == null)) |
| { |
| { |
| return false; |
| return false; |
| } |
| } |
| |
| |
| var intersects = false; |
| var intersects = false; |
| foreach (var sourceItem in source) |
| foreach (var sourceItem in source) |
| { |
| { |
| if (target.Any(a => a?.IndexOf(sourceItem, comparison) >= 0)) |
| if (target.Any(a => a?.IndexOf(sourceItem, comparison) >= 0)) |
| { |
| { |
| return true; |
| return true; |
| } |
| } |
| } |
| } |
| |
| |
| return intersects; |
| return intersects; |
| } |
| } |
| |
| |
| /// <summary> |
| /// <summary> |
| /// Checks if source collection contains any items from target one. |
| /// Checks if source collection contains any items from target one. |
| /// </summary> |
| /// </summary> |
| /// <param name="source"></param> |
| /// <param name="source"></param> |
| /// <param name="target"></param> |
| /// <param name="target"></param> |
| /// <param name="comparison"></param> |
| /// <param name="comparison"></param> |
| /// <returns>True of target collection contains items that are also part of source collection.</returns> |
| /// <returns>True of target collection contains items that are also part of source collection.</returns> |
| public static bool IntersectsExactlyWith(this IEnumerable<string> source, IEnumerable<string> target, StringComparison comparison = StringComparison.InvariantCultureIgnoreCase) |
| public static bool IntersectsExactlyWith(this IEnumerable<string> source, IEnumerable<string> target, StringComparison comparison = StringComparison.InvariantCultureIgnoreCase) |
| { |
| { |
| if (source == null && target == null) |
| if (source == null && target == null) |
| { |
| { |
| return false; |
| return false; |
| } |
| } |
| |
| |
| if ((source == null && target != null) || (source != null && target == null)) |
| if ((source == null && target != null) || (source != null && target == null)) |
| { |
| { |
| return false; |
| return false; |
| } |
| } |
| |
| |
| var intersects = false; |
| var intersects = false; |
| foreach (var sourceItem in source) |
| foreach (var sourceItem in source) |
| { |
| { |
| if (target.Any(a => a?.Equals(sourceItem, comparison) == true)) |
| if (target.Any(a => a?.Equals(sourceItem, comparison) == true)) |
| { |
| { |
| return true; |
| return true; |
| } |
| } |
| } |
| } |
| |
| |
| return intersects; |
| return intersects; |
| } |
| } |
| |
| |
| /// <summary> |
| /// <summary> |
| /// Checks if source collection constains specified string completely. |
| /// Checks if source collection constains specified string completely. |
| /// </summary> |
| /// </summary> |
| public static bool ContainsString(this IEnumerable<string> source, string value, StringComparison comparison = StringComparison.InvariantCultureIgnoreCase) |
| public static bool ContainsString(this IEnumerable<string> source, string value, StringComparison comparison = StringComparison.InvariantCultureIgnoreCase) |
| { |
| { |
| return source?.Any(a => a?.Equals(value, comparison) == true) == true; |
| return source?.Any(a => a?.Equals(value, comparison) == true) == true; |
| } |
| } |
| |
| |
| /// <summary> |
| /// <summary> |
| /// Checks if part of specified string is part of the collection. |
| /// Checks if part of specified string is part of the collection. |
| /// </summary> |
| /// </summary> |
| public static bool ContainsStringPartial(this IEnumerable<string> source, string value, StringComparison comparison = StringComparison.InvariantCultureIgnoreCase) |
| public static bool ContainsStringPartial(this IEnumerable<string> source, string value, StringComparison comparison = StringComparison.InvariantCultureIgnoreCase) |
| { |
| { |
| return source?.Any(a => a?.IndexOf(value, comparison) >= 0) == true; |
| return source?.Any(a => a?.IndexOf(value, comparison) >= 0) == true; |
| } |
| } |
| |
| |
| /// <summary> |
| /// <summary> |
| /// Checks if source collection constains part of specified string. |
| /// Checks if source collection constains part of specified string. |
| /// </summary> |
| /// </summary> |
| public static bool ContainsPartOfString(this IEnumerable<string> source, string value, StringComparison comparison = StringComparison.InvariantCultureIgnoreCase) |
| public static bool ContainsPartOfString(this IEnumerable<string> source, string value, StringComparison comparison = StringComparison.InvariantCultureIgnoreCase) |
| { |
| { |
| return source?.Any(a => value?.IndexOf(a, comparison) >= 0) == true; |
| return source?.Any(a => value?.IndexOf(a, comparison) >= 0) == true; |
| } |
| } |
| |
| |
| /// <summary> |
| /// <summary> |
| /// Checks if two collections contain the same items in any order. |
| /// Checks if two collections contain the same items in any order. |
| /// </summary> |
| /// </summary> |
| public static bool IsListEqual<T>(this IEnumerable<T> source, IEnumerable<T> target) |
| public static bool IsListEqual<T>(this IEnumerable<T> source, IEnumerable<T> target) |
| { |
| { |
| if (source == null && target == null) |
| if (source == null && target == null) |
| { |
| { |
| return true; |
| return true; |
| } |
| } |
| |
| |
| if ((source == null && target != null) || (source != null && target == null)) |
| if ((source == null && target != null) || (source != null && target == null)) |
| { |
| { |
| return false; |
| return false; |
| } |
| } |
| |
| |
| if (source.Count() != target.Count()) |
| if (source.Count() != target.Count()) |
| { |
| { |
| return false; |
| return false; |
| } |
| } |
| |
| |
. | var firstNotSecond = source.Except(target).ToList(); |
| if (source.Except(target).Any()) |
| if (firstNotSecond.Count != 0) |
| |
| { |
| { |
| return false; |
| return false; |
| } |
| } |
| |
| |
. | var secondNotFirst = target.Except(source).ToList(); |
| if (target.Except(source).Any()) |
| if (secondNotFirst.Count != 0) |
| |
| { |
| { |
| return false; |
| return false; |
| } |
| } |
| |
| |
| return true; |
| return true; |
| } |
| } |
| |
| |
| /// <summary> |
| /// <summary> |
| /// Checks if two collections contain the same items in any order. |
| /// Checks if two collections contain the same items in any order. |
| /// </summary> |
| /// </summary> |
| public static bool IsListEqual<T>(this IEnumerable<T> source, IEnumerable<T> target, IEqualityComparer<T> comparer) |
| public static bool IsListEqual<T>(this IEnumerable<T> source, IEnumerable<T> target, IEqualityComparer<T> comparer) |
| { |
| { |
| if (source == null && target == null) |
| if (source == null && target == null) |
| { |
| { |
| return true; |
| return true; |
| } |
| } |
| |
| |
| if ((source == null && target != null) || (source != null && target == null)) |
| if ((source == null && target != null) || (source != null && target == null)) |
| { |
| { |
| return false; |
| return false; |
| } |
| } |
| |
| |
| if (source.Count() != target.Count()) |
| if (source.Count() != target.Count()) |
| { |
| { |
| return false; |
| return false; |
| } |
| } |
| |
| |
. | var firstNotSecond = source.Except(target, comparer).ToList(); |
| if (source.Except(target, comparer).Any()) |
| if (firstNotSecond.Count != 0) |
| |
| { |
| { |
| return false; |
| return false; |
| } |
| } |
| |
| |
. | var secondNotFirst = target.Except(source, comparer).ToList(); |
| if (target.Except(source, comparer).Any()) |
| if (secondNotFirst.Count != 0) |
| |
| { |
| { |
| return false; |
| return false; |
| } |
| } |
| |
| |
| return true; |
| return true; |
| } |
| } |
| |
| |
| /// <summary> |
| /// <summary> |
| /// Checks if two collections contain the same items in the same order. |
| /// Checks if two collections contain the same items in the same order. |
| /// </summary> |
| /// </summary> |
| public static bool IsListEqualExact<T>(this IEnumerable<T> source, IEnumerable<T> target) |
| public static bool IsListEqualExact<T>(this IEnumerable<T> source, IEnumerable<T> target) |
| { |
| { |
| if (source == null && target == null) |
| if (source == null && target == null) |
| { |
| { |
| return true; |
| return true; |
| } |
| } |
| |
| |
| if ((source == null && target != null) || (source != null && target == null)) |
| if ((source == null && target != null) || (source != null && target == null)) |
| { |
| { |
| return false; |
| return false; |
| } |
| } |
| |
| |
| if (source.Count() != target.Count()) |
| if (source.Count() != target.Count()) |
| { |
| { |
| return false; |
| return false; |
| } |
| } |
| |
| |
| return source.SequenceEqual(target); |
| return source.SequenceEqual(target); |
| } |
| } |
| |
| |
| /// <summary> |
| /// <summary> |
| /// Check if collection contains all items from other collection (in any order). |
| /// Check if collection contains all items from other collection (in any order). |
| /// </summary> |
| /// </summary> |
| public static bool Contains<T>(this IEnumerable<T> source, IEnumerable<T> target) |
| public static bool Contains<T>(this IEnumerable<T> source, IEnumerable<T> target) |
| { |
| { |
| if (source == null && target == null) |
| if (source == null && target == null) |
| { |
| { |
| return true; |
| return true; |
| } |
| } |
| |
| |
| if ((source == null && target != null) || (source != null && target == null)) |
| if ((source == null && target != null) || (source != null && target == null)) |
| { |
| { |
| return false; |
| return false; |
| } |
| } |
| |
| |
| var targetCount = target.Count(); |
| var targetCount = target.Count(); |
| if (targetCount > source.Count()) |
| if (targetCount > source.Count()) |
| { |
| { |
| return false; |
| return false; |
| } |
| } |
| |
| |
| return target.Intersect(source).Count() == targetCount; |
| return target.Intersect(source).Count() == targetCount; |
| } |
| } |
| |
| |
| /// <summary> |
| /// <summary> |
| /// Gets items contained in all colletions. |
| /// Gets items contained in all colletions. |
| /// </summary> |
| /// </summary> |
| public static HashSet<T> GetCommonItems<T>(IEnumerable<IEnumerable<T>> lists) |
| public static HashSet<T> GetCommonItems<T>(IEnumerable<IEnumerable<T>> lists) |
| { |
| { |
| if (lists?.Any() != true || lists?.First()?.Any() != true) |
| if (lists?.Any() != true || lists?.First()?.Any() != true) |
| { |
| { |
| return new HashSet<T>(); |
| return new HashSet<T>(); |
| } |
| } |
| |
| |
| var set = new HashSet<T>(lists.First()); |
| var set = new HashSet<T>(lists.First()); |
| foreach (var list in lists) |
| foreach (var list in lists) |
| { |
| { |
| if (list == null) |
| if (list == null) |
| { |
| { |
| set.IntersectWith(new List<T>()); |
| set.IntersectWith(new List<T>()); |
| } |
| } |
| else |
| else |
| { |
| { |
| set.IntersectWith(list); |
| set.IntersectWith(list); |
| } |
| } |
| } |
| } |
| |
| |
| return set; |
| return set; |
| } |
| } |
| |
| |
| /// <summary> |
| /// <summary> |
| /// Gets items distinct to all collections. |
| /// Gets items distinct to all collections. |
| /// </summary> |
| /// </summary> |
| public static HashSet<T> GetDistinctItems<T>(IEnumerable<IEnumerable<T>> lists) |
| public static HashSet<T> GetDistinctItems<T>(IEnumerable<IEnumerable<T>> lists) |
| { |
| { |
| if (lists?.Any() != true) |
| if (lists?.Any() != true) |
| { |
| { |
| return new HashSet<T>(); |
| return new HashSet<T>(); |
| } |
| } |
| |
| |
| var set = new List<T>(); |
| var set = new List<T>(); |
| foreach (var list in lists) |
| foreach (var list in lists) |
| { |
| { |
| if (list != null) |
| if (list != null) |
| { |
| { |
| set.AddRange(list); |
| set.AddRange(list); |
| } |
| } |
| } |
| } |
| |
| |
| var listsCounts = lists.Count(); |
| var listsCounts = lists.Count(); |
| return new HashSet<T>(set.GroupBy(a => a).Where(a => a.Count() < listsCounts).Select(a => a.Key)); |
| return new HashSet<T>(set.GroupBy(a => a).Where(a => a.Count() < listsCounts).Select(a => a.Key)); |
| } |
| } |
| |
| |
| /// <summary> |
| /// <summary> |
. | |
| /// Gets items distinct to all collections. |
| |
| /// </summary> |
| |
| public static HashSet<T> GetDistinctItemsP<T>(params IEnumerable<T>[] lists) |
| |
| { |
| |
| if (lists?.Any() != true) |
| |
| { |
| |
| return new HashSet<T>(); |
| |
| } |
| |
| |
| |
| return GetDistinctItems(lists.ToList()); |
| |
| } |
| |
| |
| |
| /// <summary> |
| /// Merge collection together. |
| /// Merge collection together. |
| /// </summary> |
| /// </summary> |
| /// <typeparam name="T"></typeparam> |
| /// <typeparam name="T"></typeparam> |
| /// <param name="lists"></param> |
| /// <param name="lists"></param> |
| /// <returns></returns> |
| /// <returns></returns> |
| public static List<T> Merge<T>(IEnumerable<IEnumerable<T>> lists) |
| public static List<T> Merge<T>(IEnumerable<IEnumerable<T>> lists) |
| { |
| { |
| var allItems = new List<T>(); |
| var allItems = new List<T>(); |
| foreach (var list in lists) |
| foreach (var list in lists) |
| { |
| { |
| if (list.HasItems()) |
| if (list.HasItems()) |
| { |
| { |
| allItems.AddRange(list); |
| allItems.AddRange(list); |
| } |
| } |
| } |
| } |
| |
| |
| return allItems; |
| return allItems; |
| } |
| } |
| |
| |
| /// <summary> |
| /// <summary> |
| /// Merge two collection together. |
| /// Merge two collection together. |
| /// </summary> |
| /// </summary> |
| /// <typeparam name="T"></typeparam> |
| /// <typeparam name="T"></typeparam> |
| /// <param name="list1"></param> |
| /// <param name="list1"></param> |
| /// <param name="list2"></param> |
| /// <param name="list2"></param> |
| /// <returns></returns> |
| /// <returns></returns> |
| public static List<T> Merge<T>(IEnumerable<T> list1, IEnumerable<T> list2) |
| public static List<T> Merge<T>(IEnumerable<T> list1, IEnumerable<T> list2) |
| { |
| { |
| if (list1.HasItems() && list2.HasItems()) |
| if (list1.HasItems() && list2.HasItems()) |
| { |
| { |
| var allItems = new List<T>(list1.Count() + list2.Count()); |
| var allItems = new List<T>(list1.Count() + list2.Count()); |
| allItems.AddRange(list1); |
| allItems.AddRange(list1); |
| allItems.AddRange(list2); |
| allItems.AddRange(list2); |
. | |
| return allItems; |
| } |
| } |
| else if (list1.HasItems() && !list2.HasItems()) |
| else if (list1.HasItems() && !list2.HasItems()) |
| { |
| { |
| return list1.ToList(); |
| return list1.ToList(); |
| } |
| } |
| else if (!list1.HasItems() && list2.HasItems()) |
| else if (!list1.HasItems() && list2.HasItems()) |
| { |
| { |
| return list2.ToList(); |
| return list2.ToList(); |
| } |
| } |
| |
| |
| return new List<T>(); |
| return new List<T>(); |
| } |
| } |
| |
| |
| /// <summary> |
| /// <summary> |
| /// |
| /// |
| /// </summary> |
| /// </summary> |
| /// <typeparam name="T"></typeparam> |
| /// <typeparam name="T"></typeparam> |
| /// <param name="source"></param> |
| /// <param name="source"></param> |
| /// <param name="action"></param> |
| /// <param name="action"></param> |
| public static void ForEach<T>(this ObservableCollection<T> source, Action<T> action) |
| public static void ForEach<T>(this ObservableCollection<T> source, Action<T> action) |
| { |
| { |
| if (source.HasItems() != true) |
| if (source.HasItems() != true) |
| { |
| { |
| return; |
| return; |
| } |
| } |
| |
| |
| foreach (var item in source) |
| foreach (var item in source) |
| { |
| { |
| action(item); |
| action(item); |
| } |
| } |
. | |
| } |
| |
| |
| |
| /// <summary> |
| |
| /// |
| |
| /// </summary> |
| |
| /// <typeparam name="T"></typeparam> |
| |
| /// <param name="source"></param> |
| |
| /// <param name="action"></param> |
| |
| public static void ForEach<T>(this IEnumerable<T> source, Action<T> action) |
| |
| { |
| |
| if (source.HasItems() != true) |
| |
| { |
| |
| return; |
| |
| } |
| |
| |
| |
| foreach (var item in source) |
| |
| { |
| |
| action(item); |
| |
| } |
| |
| } |
| |
| |
| |
| /// <summary> |
| |
| /// |
| |
| /// </summary> |
| |
| /// <typeparam name="T"></typeparam> |
| |
| /// <param name="source"></param> |
| |
| /// <returns></returns> |
| |
| public static HashSet<T> ToHashSet<T>(this IEnumerable<T> source) |
| |
| { |
| |
| if (source == null) |
| |
| { |
| |
| return null; |
| |
| } |
| |
| |
| |
| if (!source.HasItems()) |
| |
| { |
| |
| return new HashSet<T>(); |
| |
| } |
| |
| |
| |
| return new HashSet<T>(source); |
| } |
| } |
| } |
| } |
| } |
| } |
| |
| |