// Copyright (c) CypherCore All rights reserved. // Licensed under the GNU GENERAL PUBLIC LICENSE. See LICENSE file in the project root for full license information. using System.Linq; namespace System.Collections.Generic { public static class CollectionExtensions { public static bool Empty(this ICollection collection) { return collection.Count == 0; } public static bool Empty(this IDictionary dictionary) { return dictionary.Count == 0; } /// /// Returns the entry in this list at the given index, or the default value of the element /// type if the index was out of bounds. /// /// The type of the elements in the list. /// The list to retrieve from. /// The index to try to retrieve at. /// The value, or the default value of the element type. public static T LookupByIndex(this IList list, int index) { return index >= list.Count ? default : list[index]; } /// /// Returns the entry in this dictionary at the given key, or the default value of the key /// if none. /// /// The key type. /// The value type. /// The dictionary to operate on. /// The key of the element to retrieve. /// The value (if any). public static TValue LookupByKey(this IDictionary dict, object key) { TValue val; TKey newkey = (TKey)Convert.ChangeType(key, typeof(TKey)); return dict.TryGetValue(newkey, out val) ? val : default; } public static TValue LookupByKey(this IDictionary dict, TKey key) { TValue val; return dict.TryGetValue(key, out val) ? val : default; } public static KeyValuePair Find(this IDictionary dict, TKey key) { if (!dict.ContainsKey(key)) return default; return new KeyValuePair(key, dict[key]); } public static bool ContainsKey(this IDictionary dict, object key) { TKey newkey = (TKey)Convert.ChangeType(key, typeof(TKey)); return dict.ContainsKey(newkey); } public static void RemoveAll(this List collection, ICheck check) { collection.RemoveAll(check.Invoke); } public static IEnumerable Shuffle(this IEnumerable source) { return source.OrderBy(x => Guid.NewGuid()); } public static void Swap(this T[] array, int position1, int position2) { // // Swaps elements in an array. Doesn't need to return a reference. // T temp = array[position1]; // Copy the first position's element array[position1] = array[position2]; // Assign to the second element array[position2] = temp; // Assign to the first element } public static void Resize(this List list, uint size) { int cur = list.Count; if (size < cur) list.RemoveRange((int)size, cur - (int)size); else { for (var i = list.Count; i < size; ++i) list.Add(default); } } public static void RandomResize(this IList list, uint size) { int listSize = list.Count; while (listSize > size) { list.RemoveAt(RandomHelper.IRand(0, listSize)); --listSize; } } public static void RandomResize(this List list, Predicate predicate, uint size) { for (var i = 0; i < list.Count; ++i) { var obj = list[i]; if (!predicate(obj)) list.Remove(obj); } if (size != 0) list.Resize(size); } public static void RandomShuffle(this IList array) { for (int n = array.Count; n > 1;) { int k = (int)RandomHelper.Rand32(n); --n; T temp = array[n]; array[n] = array[k]; array[k] = temp; } } public static void RandomShuffle(this IList array, int first, int count) { for (int n = count; n > 1;) { int k = (int)RandomHelper.Rand32(n); --n; T temp = array[n + first]; array[n + first] = array[k + first]; array[k + first] = temp; } } public static T SelectRandom(this IEnumerable source) { return source.SelectRandom(1).Single(); } public static IEnumerable SelectRandom(this IEnumerable source, uint count) { return source.Shuffle().Take((int)count); } public static T SelectRandomElementByWeight(this IEnumerable sequence, Func weightSelector) { float totalWeight = sequence.Sum(weightSelector); // The weight we are after... float itemWeightIndex = RandomHelper.NextSingle() * totalWeight; float currentWeightIndex = 0; foreach (var item in from weightedItem in sequence select new { Value = weightedItem, Weight = weightSelector(weightedItem) }) { currentWeightIndex += item.Weight; // If we've hit or passed the weight we are after for this item then it's the one we want.... if (currentWeightIndex >= itemWeightIndex) return item.Value; } return default; } public static IEnumerable Intersect(this IEnumerable first, IEnumerable second, Func comparer) { return first.Where(x => second.Count(y => comparer(x, y)) == 1); } public static uint[] ToBlockRange(this BitSet array) { uint[] blockValues = new uint[array.Length / 32 + 1]; array.CopyTo(blockValues, 0); return blockValues; } public static uint ToUInt(this BitSet array) { uint[] blockValues = new uint[array.Length / 32 + 1]; array.CopyTo(blockValues, 0); return blockValues[0]; } public static void Clear(this Array array) { Array.Clear(array, 0, array.Length); } public static void EnsureWritableListIndex(this List list, uint index, T defaultValue) { while (list.Count <= index) list.Add(defaultValue); } public static void PartitionInPlace(this IList list, Func predicate) { int left = 0; int right = list.Count - 1; while (left <= right) { while (left <= right && predicate(list[left])) { left++; } while (left <= right && !predicate(list[right])) { right--; } if (left < right) { T temp = list[left]; list[left] = list[right]; list[right] = temp; left++; right--; } } } } public interface ICheck { bool Invoke(T obj); } public delegate void IDoWork(T obj); }