531 lines
11 KiB
C#
531 lines
11 KiB
C#
using System.Collections;
|
|
using System.Collections.Generic;
|
|
using System.Text;
|
|
using System;
|
|
using Godot;
|
|
|
|
namespace Rokojori
|
|
{
|
|
|
|
|
|
public class Lists
|
|
{
|
|
public static void Sort<T>( List<T> data, Func<T,float> getValue )
|
|
{
|
|
ValueSorter<T>.SortList( data, getValue );
|
|
}
|
|
|
|
public class IndexLerpResult
|
|
{
|
|
public int closestIndex = -1;
|
|
public int secondIndex = -1;
|
|
public float lerpAmount = 0.5f;
|
|
}
|
|
|
|
|
|
public static List<T> Clone<T>( List<T> data )
|
|
{
|
|
if ( data == null )
|
|
{
|
|
return null;
|
|
}
|
|
|
|
var cloned = new List<T>( data.Count );
|
|
cloned.AddRange( data );
|
|
return cloned;
|
|
}
|
|
|
|
public static IndexLerpResult LerpIndex<T>( List<T> data, float value, Func<T,float> getValue, bool sort = false )
|
|
{
|
|
if ( sort )
|
|
{
|
|
Sort( data, getValue );
|
|
}
|
|
|
|
var result = new IndexLerpResult();
|
|
result.closestIndex = ClosestIndex<T>( data, value, getValue );
|
|
result.secondIndex = SecondClosestIndex<T>( data, result.closestIndex, value, getValue );
|
|
|
|
if ( result.closestIndex == result.secondIndex )
|
|
{
|
|
return result;
|
|
}
|
|
|
|
var closestValue = getValue( data[ result.closestIndex ] );
|
|
var secondValue = getValue( data[ result.secondIndex ] );
|
|
|
|
|
|
var min = closestValue;
|
|
var max = secondValue;
|
|
var flip = false;
|
|
|
|
if ( closestValue > secondValue )
|
|
{
|
|
flip = true;
|
|
min = secondValue;
|
|
max = closestValue;
|
|
}
|
|
|
|
result.lerpAmount = MathX.Normalize( value, min, max );
|
|
|
|
if ( flip )
|
|
{
|
|
result.lerpAmount = 1f - result.lerpAmount;
|
|
}
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
public static int SecondClosestIndex<T>( List<T> data, int closest, float compareValue, Func<T,float> getValue, bool sort = false )
|
|
{
|
|
if ( sort )
|
|
{
|
|
Sort( data, getValue );
|
|
}
|
|
|
|
if ( data.Count == 1 )
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
if ( closest == 0 )
|
|
{
|
|
return closest + 1;
|
|
}
|
|
|
|
if ( closest == data.Count - 1 )
|
|
{
|
|
return data.Count - 2;
|
|
}
|
|
|
|
var before = data[ closest - 1 ];
|
|
var after = data[ closest + 1 ];
|
|
|
|
var bD = Mathf.Abs( getValue( before ) - compareValue );
|
|
var aD = Mathf.Abs( getValue( after ) - compareValue );
|
|
|
|
if ( bD < aD )
|
|
{
|
|
return closest - 1 ;
|
|
}
|
|
|
|
return closest + 1;
|
|
}
|
|
|
|
public static int ClosestIndex<T>( List<T> data, float compareValue, Func<T,float> getValue )
|
|
{
|
|
var index = -1;
|
|
var distance = float.MaxValue;
|
|
|
|
for ( int i = 0 ; i < data.Count; i++ )
|
|
{
|
|
var d = Mathf.Abs( getValue( data[ i ] ) - compareValue );
|
|
|
|
if ( d < distance )
|
|
{
|
|
index = i;
|
|
distance = d;
|
|
}
|
|
}
|
|
|
|
return index;
|
|
}
|
|
|
|
public static List<int> CollectIndices<T>( List<T> list, Func<T,bool> evaluator )
|
|
{
|
|
var output = new List<int>();
|
|
|
|
for ( int i = 0; i < list.Count; i++ )
|
|
{
|
|
if ( evaluator( list[ i ] ) )
|
|
{
|
|
output.Add( i );
|
|
}
|
|
}
|
|
|
|
return output;
|
|
}
|
|
|
|
public static List<T> CombineAll<T>( params List<T>[] lists )
|
|
{
|
|
var list = new List<T>();
|
|
|
|
foreach ( var l in lists )
|
|
{
|
|
list.AddRange( l );
|
|
}
|
|
|
|
return list;
|
|
}
|
|
|
|
public static List<T> From<T>( params T[] elements )
|
|
{
|
|
return ToList( elements );
|
|
}
|
|
|
|
public static List<T> ToList<T>( T[] array )
|
|
{
|
|
var list = new List<T>();
|
|
list.AddRange( array );
|
|
return list;
|
|
}
|
|
|
|
public static bool Has<T>( List<T> list, T item )
|
|
{
|
|
return list.IndexOf( item ) != - 1;
|
|
}
|
|
|
|
public static T RemoveAt<T>( List<T> list, int index )
|
|
{
|
|
if ( list.Count == 0 || index < 0 || ( index > ( list.Count - 1 ) ) )
|
|
{
|
|
return default(T);
|
|
}
|
|
|
|
var first = list[ index ];
|
|
list.RemoveAt( index );
|
|
return first;
|
|
}
|
|
|
|
public static T RemoveFirst<T>( List<T> list )
|
|
{
|
|
return RemoveAt( list, 0 );
|
|
}
|
|
|
|
public static T RemoveLast<T>( List<T> list )
|
|
{
|
|
return RemoveAt( list, list.Count - 1 );
|
|
}
|
|
|
|
public static T Pop<T>( List<T> list )
|
|
{
|
|
if ( list.Count == 0 ){ return default(T); }
|
|
|
|
var element = list[ list.Count - 1 ];
|
|
list.RemoveAt( list.Count - 1 );
|
|
return element;
|
|
}
|
|
|
|
public static T Last<T>( List<T> list )
|
|
{
|
|
return list.Count == 0 ? default(T) : list[ list.Count - 1 ];
|
|
}
|
|
|
|
public static void RemoveIncreasingIndices<T>( List<T> list, List<int> removals )
|
|
{
|
|
for ( var i = removals.Count - 1; i >= 0; i-- )
|
|
{
|
|
list.RemoveAt( i );
|
|
}
|
|
}
|
|
|
|
|
|
public static int CountItems<T>( List<T> list, Predicate<T> test )
|
|
{
|
|
var result = 0;
|
|
|
|
for ( int i = 0; i < list.Count; i++ )
|
|
{
|
|
if ( test( list[ i ] ) )
|
|
{
|
|
result++;
|
|
}
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
public static int CountItems<T>( T[] list, Predicate<T> test )
|
|
{
|
|
var result = 0;
|
|
|
|
for ( int i = 0; i < list.Length; i++ )
|
|
{
|
|
if ( test( list[ i ] ) )
|
|
{
|
|
result++;
|
|
}
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
public static List<T> FromEnumerable<T>( IEnumerable enumerable )
|
|
{
|
|
var listA = new List<T>();
|
|
|
|
foreach ( var it in enumerable )
|
|
{
|
|
listA.Add( (T) it );
|
|
}
|
|
|
|
return listA;
|
|
}
|
|
|
|
public static bool AreListsAndEntriesEqual( object objA, object objB )
|
|
{
|
|
if ( ! ( ReflectionHelper.IsList( objA ) && ReflectionHelper.IsList( objB ) ) )
|
|
{
|
|
return false;
|
|
}
|
|
|
|
return AreEntriesEqual( FromEnumerable<object>( objA as IEnumerable ), FromEnumerable<object>( objB as IEnumerable ) );
|
|
}
|
|
|
|
public static bool AreEntriesEqual<T>( List<T> a, List<T> b )
|
|
{
|
|
if ( a.Count != b.Count )
|
|
{
|
|
return false;
|
|
}
|
|
|
|
for ( int i = 0; i < a.Count; i++ )
|
|
{
|
|
var isEqual = EqualityComparer<T>.Default.Equals( a[ i ], b[ i ]);
|
|
|
|
if ( ! isEqual )
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
|
|
|
|
public static string Join<T>( List<T> array, string seperator = ", " )
|
|
{
|
|
var sb = new StringBuilder();
|
|
|
|
for ( var i = 0; i < array.Count; i++ )
|
|
{
|
|
if ( i != 0 )
|
|
{
|
|
sb.Append( seperator );
|
|
}
|
|
|
|
var obj = (object) array[ i ];
|
|
|
|
RJLog.Stringify( array[ i ], sb );
|
|
}
|
|
|
|
return sb.ToString();
|
|
}
|
|
|
|
public static string Join( List<float> array, string seperator = ", " )
|
|
{
|
|
var sb = new StringBuilder();
|
|
|
|
for ( var i = 0; i < array.Count; i++ )
|
|
{
|
|
if ( i != 0 )
|
|
{
|
|
sb.Append( seperator );
|
|
}
|
|
|
|
sb.Append( RegexUtility.NumberToString( array[ i ] ) );
|
|
}
|
|
|
|
return sb.ToString();
|
|
}
|
|
|
|
|
|
public static List<T> From<T>( List<T> list )
|
|
{
|
|
var copy = new List<T>();
|
|
copy.AddRange( list );
|
|
return copy;
|
|
}
|
|
|
|
public static List<T> From<[Godot.MustBeVariant] T>( Godot.Collections.Array<T> list )
|
|
{
|
|
var copy = new List<T>();
|
|
copy.AddRange( list );
|
|
return copy;
|
|
}
|
|
|
|
public static List<U> FilterAndMap<T,U>( List<T> list, Func<T,int,bool> filter, Func<T,U> map)
|
|
{
|
|
var mapped = new List<U>();
|
|
|
|
for ( int i = 0; i < list.Count; i++ )
|
|
{
|
|
if ( ! filter( list[ i ], i ) )
|
|
{
|
|
continue;
|
|
}
|
|
|
|
mapped.Add( map( list[ i ] ) );
|
|
}
|
|
|
|
return mapped;
|
|
}
|
|
|
|
public static void Filter<T>( List<T> inputList, List<T> list, Func<T,int,bool> filter )
|
|
{
|
|
for ( int i = 0; i < inputList.Count; i++ )
|
|
{
|
|
if ( filter( inputList[ i ], i ) )
|
|
{
|
|
list.Add( inputList[ i ] );
|
|
}
|
|
}
|
|
}
|
|
|
|
public static void Filter<T>( List<T> inputList, List<T> list, Func<T,bool> filter )
|
|
{
|
|
for ( int i = 0; i < inputList.Count; i++ )
|
|
{
|
|
if ( filter( inputList[ i ] ) )
|
|
{
|
|
list.Add( inputList[ i ] );
|
|
}
|
|
}
|
|
}
|
|
|
|
public static List<T> Filter<T>( List<T> inputList, Func<T,bool> filter )
|
|
{
|
|
var list = new List<T>();
|
|
|
|
for ( int i = 0; i < inputList.Count; i++ )
|
|
{
|
|
if ( filter( inputList[ i ] ) )
|
|
{
|
|
list.Add( inputList[ i ] );
|
|
}
|
|
}
|
|
|
|
return list;
|
|
}
|
|
|
|
public static List<R> FilterType<T,R>( List<T> inputList ) where R:T
|
|
{
|
|
var list = new List<R>();
|
|
|
|
inputList.ForEach
|
|
(
|
|
e =>
|
|
{
|
|
if ( e == null || ! typeof( R ).IsAssignableFrom( e.GetType() ) )
|
|
{
|
|
return;
|
|
}
|
|
|
|
list.Add( (R) e );
|
|
}
|
|
);
|
|
|
|
return list;
|
|
}
|
|
|
|
public static void Add<T>( List<T> list, params T[] entries )
|
|
{
|
|
list.AddRange( entries );
|
|
}
|
|
|
|
public static void Insert<T>( List<T> list, T item, int index )
|
|
{
|
|
if ( index >= list.Count )
|
|
{
|
|
list.Add( item );
|
|
return;
|
|
}
|
|
|
|
index = index < 0 ? 0 : index;
|
|
|
|
list.Insert( index, item );
|
|
}
|
|
|
|
public static T Find<T>( List<T> list, Func<T,bool> callback )
|
|
{
|
|
for ( int i = 0; i < list.Count; i++ )
|
|
{
|
|
if ( callback( list[ i ] ) )
|
|
{
|
|
return list[ i ];
|
|
}
|
|
}
|
|
|
|
return default( T );
|
|
}
|
|
|
|
public static List<U> Map<T,U>( List<T> inputList, Func<T,int,U> mapper, List<U> list = null )
|
|
{
|
|
if ( list == null )
|
|
{
|
|
list = new List<U>();
|
|
}
|
|
|
|
for ( int i = 0; i < inputList.Count; i++ )
|
|
{
|
|
list.Add( mapper( inputList[ i ], i ) );
|
|
}
|
|
|
|
return list;
|
|
}
|
|
|
|
public static List<U> Map<T,U>( T[] inputList, Func<T,int,U> mapper, List<U> list = null )
|
|
{
|
|
if ( list == null )
|
|
{
|
|
list = new List<U>();
|
|
}
|
|
|
|
for ( int i = 0; i < inputList.Length; i++ )
|
|
{
|
|
list.Add( mapper( inputList[ i ], i ) );
|
|
}
|
|
|
|
return list;
|
|
}
|
|
|
|
public static List<U> Map<T,U>( List<T> inputList, Func<T,U> mapper, List<U> list = null )
|
|
{
|
|
if ( list == null )
|
|
{
|
|
list = new List<U>();
|
|
}
|
|
|
|
for ( int i = 0; i < inputList.Count; i++ )
|
|
{
|
|
list.Add( mapper( inputList[ i ] ) );
|
|
}
|
|
|
|
return list;
|
|
}
|
|
|
|
public static List<U> Map<[Godot.MustBeVariant]T,U>( Godot.Collections.Array<T> inputList, Func<T,U> mapper, List<U> list = null )
|
|
{
|
|
if ( list == null )
|
|
{
|
|
list = new List<U>();
|
|
}
|
|
|
|
for ( int i = 0; i < inputList.Count; i++ )
|
|
{
|
|
list.Add( mapper( inputList[ i ] ) );
|
|
}
|
|
|
|
return list;
|
|
}
|
|
|
|
public static List<U> Map<T,U>( T[] inputList, Func<T,U> mapper, List<U> list = null )
|
|
{
|
|
if ( list == null )
|
|
{
|
|
list = new List<U>();
|
|
}
|
|
|
|
for ( int i = 0; i < inputList.Length; i++ )
|
|
{
|
|
list.Add( mapper( inputList[ i ] ) );
|
|
}
|
|
|
|
return list;
|
|
}
|
|
|
|
|
|
}
|
|
} |