319 lines
10 KiB
C#
319 lines
10 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
|
|
namespace UnityEngine.ProBuilder
|
|
{
|
|
static class ArrayUtility
|
|
{
|
|
public static T[] ValuesWithIndexes<T>(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<T> ValuesWithIndexes<T>(this List<T> arr, IList<int> indexes)
|
|
{
|
|
List<T> vals = new List<T>(indexes.Count);
|
|
|
|
foreach (var i in indexes)
|
|
vals.Add(arr[i]);
|
|
|
|
return vals;
|
|
}
|
|
|
|
public static IEnumerable<int> AllIndexesOf<T>(this IList<T> list, Func<T, bool> lambda)
|
|
{
|
|
var indexes = new List<int>();
|
|
for (int i = 0, c = list.Count; i < c; i++)
|
|
if (lambda(list[i]))
|
|
indexes.Add(i);
|
|
return indexes;
|
|
}
|
|
|
|
public static T[] Add<T>(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<T>(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<T>(this T[] arr, T val)
|
|
{
|
|
List<T> list = new List<T>(arr);
|
|
list.Remove(val);
|
|
return list.ToArray();
|
|
}
|
|
|
|
public static T[] Remove<T>(this T[] arr, IEnumerable<T> val)
|
|
{
|
|
return arr.Except(val).ToArray();
|
|
}
|
|
|
|
public static T[] RemoveAt<T>(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<T>(this IList<T> list, IEnumerable<int> indexes)
|
|
{
|
|
List<int> sorted = new List<int>(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<T>(this IList<T> list, IList<int> 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<T>(IList<T> sorted_list, T value) where T : System.IComparable<T>
|
|
{
|
|
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<T> Fill<T>(System.Func<int, T> ctor, int length)
|
|
{
|
|
List<T> list = new List<T>(length);
|
|
for (int i = 0; i < length; i++)
|
|
list.Add(ctor(i));
|
|
return list;
|
|
}
|
|
|
|
public static T[] Fill<T>(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<T>(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<T>(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<T>(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<T>(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<T>(this List<List<T>> 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<T>(int count, System.Func<int, T> 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<T, K>(this Dictionary<T, List<K>> dictionary, T key, K value)
|
|
{
|
|
List<K> list;
|
|
|
|
if (dictionary.TryGetValue(key, out list))
|
|
list.Add(value);
|
|
else
|
|
dictionary.Add(key, new List<K>() { value });
|
|
}
|
|
|
|
/**
|
|
* Add a value to a key in dictionary, adding a new entry if necessray.
|
|
*/
|
|
public static void AddOrAppendRange<T, K>(this Dictionary<T, List<K>> dictionary, T key, List<K> value)
|
|
{
|
|
List<K> 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<TSource> DistinctBy<TSource, TKey>(
|
|
this IEnumerable<TSource> source,
|
|
Func<TSource, TKey> keySelector)
|
|
{
|
|
HashSet<TKey> knownKeys = new HashSet<TKey>();
|
|
return source.Where(x => knownKeys.Add(keySelector(x)));
|
|
}
|
|
|
|
public static string ToString<TKey, TValue>(this Dictionary<TKey, TValue> dict)
|
|
{
|
|
System.Text.StringBuilder sb = new System.Text.StringBuilder();
|
|
|
|
foreach (KeyValuePair<TKey, TValue> kvp in dict)
|
|
sb.AppendLine(string.Format("Key: {0} Value: {1}", kvp.Key, kvp.Value));
|
|
return sb.ToString();
|
|
}
|
|
|
|
public static string ToString<T>(this IEnumerable<T> arr, string separator = ", ")
|
|
{
|
|
return string.Join(separator, arr.Select(x => x.ToString()).ToArray());
|
|
}
|
|
}
|
|
}
|