TurnBasedStrategyCourse/Library/PackageCache/com.unity.probuilder@5.1.0/Runtime/Core/ArrayUtility.cs

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());
}
}
}