using System; using System.Collections.Generic; using System.Linq; namespace QFSW.QC.Utilities { public static class CollectionExtensions { /// Inverts the key/value relationship between the items in the dictionary. /// Dictionary with the inverted relationship. public static Dictionary Invert(this IDictionary source) { Dictionary dictionary = new Dictionary(); foreach (KeyValuePair item in source) { if (!dictionary.ContainsKey(item.Value)) { dictionary.Add(item.Value, item.Key); } } return dictionary; } /// Gets a sub array of an existing array. /// Index to take the sub array from. /// The length of the sub array. public static T[] SubArray(this T[] data, int index, int length) { T[] result = new T[length]; Array.Copy(data, index, result, 0, length); return result; } /// Skips the last element in the sequence. public static IEnumerable SkipLast(this IEnumerable source) { using (IEnumerator enumurator = source.GetEnumerator()) { if (enumurator.MoveNext()) { for (T value = enumurator.Current; enumurator.MoveNext(); value = enumurator.Current) { yield return value; } } } } /// Reverses the order of the sequence. public static IEnumerable Reversed(this IReadOnlyList source) { for (int i = source.Count - 1; i >= 0; i--) { yield return source[i]; } } /// /// Creates a distinct stream based on a custom predicate. /// /// The type of the IEnumerable. /// The type of the value to test for distinctness. /// The source IEnumerable. /// The custom distinct item producer. /// The distinct stream. public static IEnumerable DistinctBy(this IEnumerable source, Func predicate) { HashSet set = new HashSet(); foreach (TValue value in source) { if (set.Add(predicate(value))) { yield return value; } } } public static IEnumerable Yield(this T item) { yield return item; } public static T LastOr(this IEnumerable source, T value) { try { return source.Last(); } catch (InvalidOperationException) { return value; } } public static unsafe void InsertionSortBy(this IList collection, Func keySelector) { const int maxStackSize = 512; if (collection.Count <= maxStackSize) { int* keyBuffer = stackalloc int[collection.Count]; InsertionSortBy(collection, keySelector, keyBuffer); } else { int[] keyArray = new int[collection.Count]; fixed (int* keyBuffer = keyArray) { InsertionSortBy(collection, keySelector, keyBuffer); } } } private static unsafe void InsertionSortBy(this IList collection, Func keySelector, int* keyBuffer) { int n = collection.Count; for (int i = 0; i < n; i++) { keyBuffer[i] = keySelector(collection[i]); } for (int i = 1; i < n; i++) { T item = collection[i]; int key = keyBuffer[i]; int j = i - 1; while (j >= 0 && keyBuffer[j] > key) { collection[j + 1] = collection[j]; keyBuffer[j + 1] = keyBuffer[j]; j -= 1; } collection[j + 1] = item; keyBuffer[j + 1] = key; } } } }