E:\Devel\PlayniteDiagTool\PlayniteDiagTool\bin\Debug\temp\PlayniteSDK\Extensions\ListExtensions.cs e:\Devel\Playnite\source\PlayniteSDK\Extensions\ListExtensions.cs
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);
       }        }
   }    }
} }