using System; using System.Collections.Generic; using System.Linq; namespace Ips.Library.Basic { public static class ListExtensions { public static void InsertRange(this IList source, int index, IEnumerable items) { foreach (var item in items) { source.Insert(index++, item); } } public static int FindIndex(this IList source, Predicate selector) { for (var i = 0; i < source.Count; ++i) { if (selector(source[i])) { return i; } } return -1; } public static void AddFirst(this IList source, T item) { source.Insert(0, item); } public static void AddLast(this IList source, T item) { source.Insert(source.Count, item); } public static void InsertAfter(this IList source, T existingItem, T item) { var index = source.IndexOf(existingItem); if (index < 0) { source.AddFirst(item); return; } source.Insert(index + 1, item); } public static void InsertAfter(this IList source, Predicate selector, T item) { var index = source.FindIndex(selector); if (index < 0) { source.AddFirst(item); return; } source.Insert(index + 1, item); } public static void InsertBefore(this IList source, T existingItem, T item) { var index = source.IndexOf(existingItem); if (index < 0) { source.AddLast(item); return; } source.Insert(index, item); } public static void InsertBefore(this IList source, Predicate selector, T item) { var index = source.FindIndex(selector); if (index < 0) { source.AddLast(item); return; } source.Insert(index, item); } public static void ReplaceWhile(this IList source, Predicate selector, T item) { for (int i = 0; i < source.Count; i++) { if (selector(source[i])) { source[i] = item; } } } public static void ReplaceWhile(this IList source, Predicate selector, Func itemFactory) { for (int i = 0; i < source.Count; i++) { var item = source[i]; if (selector(item)) { source[i] = itemFactory(item); } } } public static void ReplaceOne(this IList source, Predicate selector, T item) { for (int i = 0; i < source.Count; i++) { if (selector(source[i])) { source[i] = item; return; } } } public static void ReplaceOne(this IList source, Predicate selector, Func itemFactory) { for (int i = 0; i < source.Count; i++) { var item = source[i]; if (selector(item)) { source[i] = itemFactory(item); return; } } } public static void ReplaceOne(this IList source, T item, T replaceWith) { for (int i = 0; i < source.Count; i++) { if (Comparer.Default.Compare(source[i], item) == 0) { source[i] = replaceWith; return; } } } public static void MoveItem(this List source, Predicate selector, int targetIndex) { var currentIndex = source.FindIndex(0, selector); if (currentIndex == targetIndex) { return; } var item = source[currentIndex]; source.RemoveAt(currentIndex); source.Insert(targetIndex, item); } public static T GetOrAdd(this IList source, Func selector, Func factory) { var item = source.FirstOrDefault(selector); if (item == null) { item = factory(); source.Add(item); } return item; } public static List SortByDependencies( this IEnumerable source, Func> getDependencies, IEqualityComparer comparer = null) { var sorted = new List(); var visited = new Dictionary(comparer); foreach (var item in source) { SortByDependenciesVisit(item, getDependencies, sorted, visited); } return sorted; } private static void SortByDependenciesVisit(T item, Func> getDependencies, List sorted, Dictionary visited) { bool inProcess; var alreadyVisited = visited.TryGetValue(item, out inProcess); if (alreadyVisited) { if (inProcess) { throw new ArgumentException("Cyclic dependency found! Item: " + item); } } else { visited[item] = true; var dependencies = getDependencies(item); if (dependencies != null) { foreach (var dependency in dependencies) { SortByDependenciesVisit(dependency, getDependencies, sorted, visited); } } visited[item] = false; sorted.Add(item); } } } }