You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
283 lines
7.6 KiB
283 lines
7.6 KiB
using System;
|
|
using System.Collections.Generic;
|
|
using System.Numerics;
|
|
using Unity.VisualScripting;
|
|
|
|
public static class CustomExtension
|
|
{
|
|
/// <summary>
|
|
/// insert value to list and sort.
|
|
/// </summary>
|
|
static public void OrderInsert<T>(this IList<T> arr, T value, Func<T, T, int> comparison)
|
|
{
|
|
arr.Add(value);
|
|
|
|
for (int i = arr.Count - 1; i > 0; --i)
|
|
{
|
|
if (comparison(arr[i - 1], arr[i]) > 0)
|
|
{
|
|
T tmp = arr[i];
|
|
arr[i] = arr[i - 1];
|
|
arr[i - 1] = tmp;
|
|
}
|
|
else
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// sort list.
|
|
/// </summary>
|
|
static public void InsertionSort<T>(this IList<T> arr, Func<T, T, int> comparison)
|
|
{
|
|
for (int i = 1; i < arr.Count; ++i)
|
|
{
|
|
for (int j = i; j > 0; --j)
|
|
{
|
|
if (comparison(arr[j - 1], arr[j]) > 0)
|
|
{
|
|
T tmp = arr[j];
|
|
arr[j] = arr[j - 1];
|
|
arr[j - 1] = tmp;
|
|
}
|
|
else
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// sort list.
|
|
/// </summary>
|
|
static public void InsertionSort<T>(this IList<T> arr, Func<T, T, bool> comparison)
|
|
{
|
|
InsertionSort(arr, (a, b) => comparison(a, b) ? 1 : -1);
|
|
}
|
|
|
|
/// <summary>
|
|
/// insert value to dictionary, if key is exist, replace value.
|
|
/// </summary>
|
|
static public void SafeInsert<TKey, TValue>(this IDictionary<TKey, TValue> dic, TKey key, TValue value)
|
|
{
|
|
if (dic.ContainsKey(key)) dic[key] = value;
|
|
else dic.Add(key, value);
|
|
}
|
|
|
|
/// <summary>
|
|
/// insert value to dictionary, if key is exist, replace value.
|
|
/// </summary>
|
|
static public void SafeInsert<TKey, TValue>(this IDictionary<TKey, TValue> dic, KeyValuePair<TKey, TValue> kvPair)
|
|
{
|
|
SafeInsert(dic, kvPair.Key, kvPair.Value);
|
|
}
|
|
|
|
/// <summary>
|
|
/// get value from dictionary, if key is not exist, return default value.
|
|
/// </summary>
|
|
static public TValue SafeGet<TKey, TValue>(this IDictionary<TKey, TValue> dic, TKey key)
|
|
{
|
|
if (dic.ContainsKey(key)) return dic[key];
|
|
else return default;
|
|
}
|
|
|
|
static public bool TryGetRandomValue<TKey, TValue>(this IDictionary<TKey, TValue> dic, out TValue result)
|
|
{
|
|
result = default;
|
|
|
|
int rnd = UnityEngine.Random.Range(0, dic.Count);
|
|
foreach (var kv in dic)
|
|
{
|
|
if (rnd-- == 0)
|
|
{
|
|
result = kv.Value;
|
|
return true;
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
/// <summary>
|
|
/// get value from list, if index less than 0, return first value. if index greater than list count, return last value.
|
|
/// </summary>
|
|
static public TValue ClampGet<TValue>(this IList<TValue> list, int index)
|
|
{
|
|
if(list.Count == 0)
|
|
throw new Exception("list is empty");
|
|
|
|
if(index < 0) return list[0];
|
|
else if (index >= list.Count) return list[list.Count - 1];
|
|
else return list[index];
|
|
}
|
|
|
|
/// <summary>
|
|
/// try get value from list, if index is not valid, return false.
|
|
/// </summary>
|
|
static public bool TryGetValueAt<TValue>(this IList<TValue> list, int index, out TValue result)
|
|
{
|
|
if(index >= 0 && index < list.Count)
|
|
{
|
|
result = list[index];
|
|
return true;
|
|
}
|
|
else
|
|
{
|
|
result = default;
|
|
return false;
|
|
}
|
|
}
|
|
|
|
static public bool TryFind<TValue>(this IList<TValue> list, Predicate<TValue> match, out TValue result)
|
|
{
|
|
foreach(var item in list)
|
|
{
|
|
if(match(item))
|
|
{
|
|
result = item;
|
|
return true;
|
|
}
|
|
}
|
|
|
|
result = default;
|
|
return false;
|
|
}
|
|
|
|
static public bool TryBinarySearch<TValue>(this IList<TValue> list, TValue value, Comparison<TValue> comparison, out int index) => TryBinarySearch(list, (v) => comparison(v, value), out index);
|
|
|
|
static public bool TryBinarySearch<TValue>(this IList<TValue> list, Func<TValue, int> comparison, out int index)
|
|
{
|
|
int low = 0;
|
|
int high = list.Count - 1;
|
|
|
|
index = -1;
|
|
while (low <= high)
|
|
{
|
|
int mid = (low + high) / 2;
|
|
int cmp = comparison(list[mid]);
|
|
|
|
if (cmp == 0)
|
|
{
|
|
index = mid;
|
|
break;
|
|
}
|
|
else if (cmp < 0)
|
|
{
|
|
low = mid + 1;
|
|
}
|
|
else
|
|
{
|
|
high = mid - 1;
|
|
}
|
|
}
|
|
|
|
return index != -1;
|
|
}
|
|
|
|
/// <summary>
|
|
/// try get random value from list, if list is empty, return false.
|
|
/// </summary>
|
|
static public bool TryGetRandomValue<TValue>(this IList<TValue> list, out TValue result)
|
|
{
|
|
if(list.Count == 0)
|
|
{
|
|
result = default;
|
|
return false;
|
|
}
|
|
|
|
result = list[UnityEngine.Random.Range(0, list.Count)];
|
|
return true;
|
|
}
|
|
|
|
/// <summary>
|
|
/// set elements with given range to value.
|
|
/// </summary>
|
|
static public void SetElements<TValue>(this IList<TValue> list, TValue value, int offset, int count)
|
|
{
|
|
for(int i = offset; i < offset + count; ++i)
|
|
{
|
|
if(i < 0 || i >= list.Count) continue;
|
|
list[i] = value;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// set all elements to value.
|
|
/// </summary>
|
|
static public void SetElements<TValue>(this IList<TValue> list, TValue value)
|
|
{
|
|
SetElements(list, value, 0, list.Count);
|
|
}
|
|
|
|
/// <summary>
|
|
/// swapping elements with predict
|
|
/// </summary>
|
|
static public int SwapElements<TValue>(this IList<TValue> list, Func<TValue, bool> predict)
|
|
{
|
|
const int needSetFlag = 0;
|
|
const int trueFlag = 1;
|
|
const int falseFlag = 2;
|
|
|
|
int ret = -1;
|
|
int[] flags = new int[list.Count];
|
|
for(int i = 0; i < list.Count; ++i)
|
|
{
|
|
if (flags[i] == needSetFlag) flags[i] = predict(list[i]) ? trueFlag : falseFlag;
|
|
if (flags[i] == trueFlag) continue;
|
|
|
|
int j;
|
|
for(j = i + 1; j < list.Count; ++j)
|
|
{
|
|
if (flags[j] == needSetFlag) flags[j] = predict(list[j]) ? trueFlag : falseFlag;
|
|
if (flags[j] == falseFlag) continue;
|
|
|
|
TValue tmp = list[i];
|
|
list[i] = list[j];
|
|
list[j] = tmp;
|
|
flags[i] = trueFlag;
|
|
flags[j] = falseFlag;
|
|
break;
|
|
}
|
|
|
|
ret = i;
|
|
if(j == list.Count) break;
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
static public void Shuffle<TValue>(this IList<TValue> list)
|
|
{
|
|
int n = list.Count;
|
|
while (n > 1)
|
|
{
|
|
n--;
|
|
int rndIdx = UnityEngine.Random.Range(0, n + 1);
|
|
|
|
TValue tmp = list[rndIdx];
|
|
list[rndIdx] = list[n];
|
|
list[n] = tmp;
|
|
}
|
|
}
|
|
|
|
public static bool EqualsUpToSeconds(this DateTime dt1, DateTime dt2)
|
|
{
|
|
return dt1.Year == dt2.Year && dt1.Month == dt2.Month && dt1.Day == dt2.Day &&
|
|
dt1.Hour == dt2.Hour && dt1.Minute == dt2.Minute && dt1.Second == dt2.Second;
|
|
}
|
|
|
|
public static BigInteger Multiply(this BigInteger a, float b)
|
|
{
|
|
return (a * (BigInteger)(b * 1000)) / 1000;
|
|
}
|
|
|
|
public static BigInteger Divide(this BigInteger a, float b)
|
|
{
|
|
return (a * 1000) / (BigInteger)(b * 1000);
|
|
}
|
|
}
|
|
|
|
|