#nullable disable using System; using System.Collections.Generic; using System.Linq; namespace BizHawk.Common.CollectionExtensions { public static class CollectionExtensions { public static int LowerBoundBinarySearch(this IList list, Func keySelector, TKey key) where TKey : IComparable { int min = 0; int max = list.Count; int mid; TKey midKey; while (min < max) { mid = (max + min) / 2; T midItem = list[mid]; midKey = keySelector(midItem); int comp = midKey.CompareTo(key); if (comp < 0) { min = mid + 1; } else if (comp > 0) { max = mid - 1; } else { return mid; } } // did we find it exactly? if (min == max && keySelector(list[min]).CompareTo(key) == 0) { return min; } mid = min; // we didnt find it. return something corresponding to lower_bound semantics if (mid == list.Count) { return max; // had to go all the way to max before giving up; lower bound is max } if (mid == 0) { return -1; // had to go all the way to min before giving up; lower bound is min } midKey = keySelector(list[mid]); if (midKey.CompareTo(key) >= 0) { return mid - 1; } return mid; } /// not found after mapping over /// implementation from https://stackoverflow.com/a/1766369/7467292 public static T BinarySearch(this IList list, Func keySelector, TKey key) where TKey : IComparable { int min = 0; int max = list.Count; while (min < max) { int mid = (max + min) / 2; T midItem = list[mid]; TKey midKey = keySelector(midItem); int comp = midKey.CompareTo(key); if (comp < 0) { min = mid + 1; } else if (comp > 0) { max = mid - 1; } else { return midItem; } } if (min == max && keySelector(list[min]).CompareTo(key) == 0) { return list[min]; } throw new InvalidOperationException("Item not found"); } #if true public static Dictionary SimpleCopy(this IEnumerable> dict) { var entryList = dict.ToList(); var copy = new Dictionary(); for (int i = 0, l = entryList.Count; i != l; i++) { var entry = entryList[i]; copy.Add(entry.Key, entry.Value); } return copy; } #else // faster? public static Dictionary SimpleCopy(this IEnumerable> dict) { var copy = new Dictionary(); using var @enum = dict.GetEnumerator(); @enum.Reset(); KeyValuePair entry; while (@enum.MoveNext()) { entry = @enum.Current; copy.Add(entry.Key, entry.Value); } return copy; } #endif public static List SimpleCopy(this IList list) { var copy = new List(); for (int i = 0, l = list.Count; i != l; i++) copy[i] = list[i]; return copy; } } }