rj-action-library/Runtime/Tools/Lists.cs

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