using System; using System.Collections.Generic; using System.Linq; namespace UnityEngine.ProBuilder { static class ArrayUtility { public static T[] ValuesWithIndexes(this T[] arr, int[] indexes) { T[] vals = new T[indexes.Length]; for (int i = 0; i < indexes.Length; i++) vals[i] = arr[indexes[i]]; return vals; } public static List ValuesWithIndexes(this List arr, IList indexes) { List vals = new List(indexes.Count); foreach (var i in indexes) vals.Add(arr[i]); return vals; } public static IEnumerable AllIndexesOf(this IList list, Func lambda) { var indexes = new List(); for (int i = 0, c = list.Count; i < c; i++) if (lambda(list[i])) indexes.Add(i); return indexes; } public static T[] Add(this T[] arr, T val) { T[] v = new T[arr.Length + 1]; System.Array.ConstrainedCopy(arr, 0, v, 0, arr.Length); v[arr.Length] = val; return v; } public static T[] AddRange(this T[] arr, T[] val) { T[] ret = new T[arr.Length + val.Length]; System.Array.ConstrainedCopy(arr, 0, ret, 0, arr.Length); System.Array.ConstrainedCopy(val, 0, ret, arr.Length, val.Length); return ret; } /** * Remove @val from @arr. */ public static T[] Remove(this T[] arr, T val) { List list = new List(arr); list.Remove(val); return list.ToArray(); } public static T[] Remove(this T[] arr, IEnumerable val) { return arr.Except(val).ToArray(); } public static T[] RemoveAt(this T[] arr, int index) { T[] newArray = new T[arr.Length - 1]; int n = 0; for (int i = 0; i < arr.Length; i++) { if (i != index) { newArray[n] = arr[i]; n++; } } return newArray; } public static T[] RemoveAt(this IList list, IEnumerable indexes) { List sorted = new List(indexes); sorted.Sort(); return SortedRemoveAt(list, sorted); } /** * Remove elements at indexes from an array, but accepts a pre-sorted indexes list. */ public static T[] SortedRemoveAt(this IList list, IList sorted) { int indexeSortedCount = sorted.Count; int len = list.Count; T[] newArray = new T[len - indexeSortedCount]; int n = 0; for (int i = 0; i < len; i++) { if (n < indexeSortedCount && sorted[n] == i) { // handle duplicate indexes while (n < indexeSortedCount && sorted[n] == i) n++; continue; } newArray[i - n] = list[i]; } return newArray; } /** * Holds a start and end index for a binary search. */ struct SearchRange { public int begin, end; public SearchRange(int begin, int end) { this.begin = begin; this.end = end; } public bool Valid() { return end - begin > 1; } public int Center() { return begin + (end - begin) / 2; } public override string ToString() { return "{" + begin + ", " + end + "} : " + Center(); } } /** * Given a sorted list and value, returns the index of the greatest value in sorted_list that is * less than value. Ex: List( { 0, 1, 4, 6, 7 } ) Value(5) returns 2, which is the index of value 4. * If value is less than sorted[0], -1 is returned. If value is greater than sorted[end], sorted.Count-1 * is returned. If an exact match is found, the index prior to that match is returned. */ public static int NearestIndexPriorToValue(IList sorted_list, T value) where T : System.IComparable { int count = sorted_list.Count; if (count < 1) return -1; SearchRange range = new SearchRange(0, count - 1); if (value.CompareTo(sorted_list[0]) < 0) return -1; if (value.CompareTo(sorted_list[count - 1]) > 0) return count - 1; while (range.Valid()) { if (sorted_list[range.Center()].CompareTo(value) > 0) { // sb.AppendLine(sorted_list[range.Center()] + " > " + value + " [" + range.begin + ", " + range.end +"] -> [" + range.begin + ", " + range.Center() + "]"); range.end = range.Center(); } else { // sb.AppendLine(sorted_list[range.Center()] + " < " + value + " [" + range.begin + ", " + range.end +"] -> [" + range.Center() + ", " + range.end + "]"); range.begin = range.Center(); if (sorted_list[range.begin + 1].CompareTo(value) >= 0) { return range.begin; } } } return 0; } public static List Fill(System.Func ctor, int length) { List list = new List(length); for (int i = 0; i < length; i++) list.Add(ctor(i)); return list; } public static T[] Fill(T val, int length) { T[] arr = new T[length]; for (int i = 0; i < length; i++) { arr[i] = val; } return arr; } /** * True if any value is present in both arrays. */ public static bool ContainsMatch(this T[] a, T[] b) { int ind = -1; for (int i = 0; i < a.Length; i++) { ind = System.Array.IndexOf(b, a[i]); if (ind > -1) return true;//ind; } return false;// ind; } /** * True if any value is present in both arrays, setting index_a and index_b to the index in the array of each match. */ public static bool ContainsMatch(this T[] a, T[] b, out int index_a, out int index_b) { index_b = -1; for (index_a = 0; index_a < a.Length; index_a++) { index_b = Array.IndexOf(b, a[index_a]); if (index_b > -1) return true; //ind; } return false; // ind; } /** * Concatenate two arrays. */ public static T[] Concat(this T[] x, T[] y) { if (x == null) throw new ArgumentNullException("x"); if (y == null) throw new ArgumentNullException("y"); int oldLen = x.Length; Array.Resize(ref x, x.Length + y.Length); Array.Copy(y, 0, x, oldLen, y.Length); return x; } /** * Returns the index of the array that contains this value. -1 if not found. */ public static int IndexOf(this List> InList, T InValue) { for (int i = 0; i < InList.Count; i++) { for (int x = 0; x < InList[i].Count; x++) if (InList[i][x].Equals(InValue)) return i; } return -1; } /** * Generate a new array with count using the constructor. ctor recieves the index and returns a new instance of T. */ public static T[] Fill(int count, System.Func ctor) { T[] arr = new T[count]; for (int i = 0; i < count; i++) arr[i] = ctor(i); return arr; } /** * Add a value to a key in dictionary, adding a new entry if necessray. */ public static void AddOrAppend(this Dictionary> dictionary, T key, K value) { List list; if (dictionary.TryGetValue(key, out list)) list.Add(value); else dictionary.Add(key, new List() { value }); } /** * Add a value to a key in dictionary, adding a new entry if necessray. */ public static void AddOrAppendRange(this Dictionary> dictionary, T key, List value) { List list; if (dictionary.TryGetValue(key, out list)) list.AddRange(value); else dictionary.Add(key, value); } /** * http://stackoverflow.com/questions/1300088/distinct-with-lambda */ public static IEnumerable DistinctBy( this IEnumerable source, Func keySelector) { HashSet knownKeys = new HashSet(); return source.Where(x => knownKeys.Add(keySelector(x))); } public static string ToString(this Dictionary dict) { System.Text.StringBuilder sb = new System.Text.StringBuilder(); foreach (KeyValuePair kvp in dict) sb.AppendLine(string.Format("Key: {0} Value: {1}", kvp.Key, kvp.Value)); return sb.ToString(); } public static string ToString(this IEnumerable arr, string separator = ", ") { return string.Join(separator, arr.Select(x => x.ToString()).ToArray()); } } }