添加基础枚举扩展

This commit is contained in:
2023-10-29 17:56:31 +08:00
parent e2ca273696
commit e293c5592d
6 changed files with 456 additions and 10 deletions
+145
View File
@@ -1,7 +1,10 @@
using Codice.CM.WorkspaceServer.Tree.GameUI.HeadTree;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.CompilerServices;
using Unity.VisualScripting.YamlDotNet.Core.Tokens;
@@ -156,4 +159,146 @@ namespace XericLibrary.Runtime.MacroLibrary
return isValid > 0 && isFull <= 0;
}
}
public static partial class MacroMath
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private static int EnumToInt32(this Enum target)
{
return Convert.ToInt32(target);
}
/// <summary>
/// 枚举仅此有效
/// </summary>
/// <param name="target"></param>
/// <param name="value"></param>
/// <returns></returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static bool EnumJust(this Enum target, Enum value)
{
return target.EnumToInt32() == value.EnumToInt32();
}
/// <summary>
/// 枚举至少存在一个有效的枚举项目
/// </summary>
/// <returns>返回是否存在至少有一个有效的枚举项目</returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static bool EnumGreater(this Enum target)
{
return target.EnumToInt32() > 0;
}
/// <summary>
/// 枚举至少存在一个有效的枚举项目
/// </summary>
/// <returns>返回是否存在至少有一个有效的枚举项目</returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static bool EnumGreater(this Enum target, Enum value)
{
return (target.EnumToInt32() & value.EnumToInt32()) > 0;
}
/// <summary>
/// 枚举1有效
/// </summary>
/// <returns></returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static bool EnumGreater1(this Enum target)
{
return (target.EnumToInt32() & 01) > 0;
}
/// <summary>
/// 枚举2有效
/// </summary>
/// <returns></returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static bool EnumGreater2(this Enum target)
{
return (target.EnumToInt32() & 02) > 0;
}
/// <summary>
/// 枚举3有效
/// </summary>
/// <returns></returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static bool EnumGreater3(this Enum target)
{
return (target.EnumToInt32() & 04) > 0;
}
/// <summary>
/// 枚举4有效
/// </summary>
/// <returns></returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static bool EnumGreater4(this Enum target)
{
return (target.EnumToInt32() & 010) > 0;
}
/// <summary>
/// 枚举5有效
/// </summary>
/// <returns></returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static bool EnumGreater5(this Enum target)
{
return (target.EnumToInt32() & 020) > 0;
}
/// <summary>
/// 枚举6有效
/// </summary>
/// <returns></returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static bool EnumGreater6(this Enum target)
{
return (target.EnumToInt32() & 030) > 0;
}
/// <summary>
/// 枚举7有效
/// </summary>
/// <returns></returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static bool EnumGreater7(this Enum target)
{
return (target.EnumToInt32() & 040) > 0;
}
/// <summary>
/// 枚举8有效
/// </summary>
/// <returns></returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static bool EnumGreater8(this Enum target)
{
return (target.EnumToInt32() & 0100) > 0;
}
/// <summary>
/// 枚举小于0,或者说不存在有效的枚举项目
/// </summary>
/// <returns>返回是否不存在有效的枚举项目</returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static bool EnumLess(this Enum target)
{
return target.EnumToInt32() <= 0;
}
/// <summary>
/// 枚举小于0,或者说不存在有效的枚举项目
/// </summary>
/// <returns>返回是否不存在有效的枚举项目</returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static bool EnumLess(this Enum target, Enum value)
{
return (target.EnumToInt32() & value.EnumToInt32()) <= 0;
}
}
}
+89
View File
@@ -0,0 +1,89 @@
using System;
using System.Collections;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using UnityEngine;
namespace XericLibrary.Runtime.MacroLibrary
{
public static partial class MacroMath
{
#region
/// <summary>
/// Fisher-Yates洗牌算法,时间复杂度为O(n*n),空间复杂度为O(n)
/// </summary>
/// <param name="length">待选项目的索引长度</param>
/// <param name="select">输出项目的索引长度</param>
/// <returns></returns>
public static List<int> FisherYatesShuffle(int length, int select)
{
var random = new System.Random();
List<int> arr = Enumerable.Range(1, length).ToList();
List<int> res = new List<int>();
for(int i = 0; i < select; ++i)
{
int k = random.Next(arr.Count);
res.Add(arr[k]);
arr.RemoveAt(k);
}
return res;
}
/// <summary>
/// 蓄水池抽样算法,可以在线程安全的情况下完成洗牌。
/// </summary>
/// <param name="arr"></param>
/// <param name="select">需要抽取的样本 M</param>
/// <param name="reservoir"></param>
/// <param name="cancellationToken"></param>
public static void ReservoirSampling(List<int> arr, int select, ConcurrentBag<int> reservoir, CancellationToken cancellationToken)
{
/**
* int M = 3; // 需要抽样的元素个数
* int totalElements = 10; // 输入数据的总元素个数
* var arr = new List<int>();
*
* for (int i = 1; i <= totalElements; i++)
* {
* arr.Add(i);
* }
*
* ConcurrentBag<int> reservoir = new ConcurrentBag<int>();
* Random random = new Random();
*
* var cancellationTokenSource = new CancellationTokenSource();
* var cancellationToken = cancellationTokenSource.Token;
*
* ThreadPool.QueueUserWorkItem(state =>
* ReservoirSampling(arr, M, reservoir, random, cancellationToken);
* , null);
*
* // 停止抽样
* cancellationTokenSource.Cancel();
*/
var random = new System.Random();
for(int i = select; i < arr.Count; ++i)
{
if(cancellationToken.IsCancellationRequested)
return;
int k = random.Next(i + 1); // 生成一个随机数 k,范围是 [0, i]
if(k < select)
{
// 如果 k 小于 M,将 arr[k] 添加到抽样结果中
reservoir.Add(arr[k]);
}
}
}
#endregion
}
}
+11
View File
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 696a363a0af92ff428710da4ee9e85a7
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
+25
View File
@@ -47,6 +47,7 @@ namespace XericLibrary.Runtime.MacroLibrary
return index;
}
#endregion
#region
@@ -139,5 +140,29 @@ namespace XericLibrary.Runtime.MacroLibrary
#endregion
#region
/// <summary>
/// 获取被从A到B的值填充的列表
/// </summary>
/// <param name="a"></param>
/// <param name="b"></param>
/// <returns></returns>
public static List<int> GetListFormAToB(int a, int b)
{
var list = new List<int>();
bool way = a > b;
var step = way ? -1 : 1;
for(int i = a; (!way && i <= b) || (way && i >= b); i += step)
list.Add(i);
return list;
}
#endregion
}
}
+145 -9
View File
@@ -1,5 +1,8 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;
namespace XericLibrary.Runtime.MacroLibrary
@@ -8,11 +11,91 @@ namespace XericLibrary.Runtime.MacroLibrary
{
#region
/// <summary>
/// 获取此枚举器在给定索引下的值
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="target"></param>
/// <param name="index"></param>
/// <returns></returns>
/// <exception cref="IndexOutOfRangeException"></exception>
public static T SelectIndex<T>(this IEnumerable<T> target, int index)
{
int nowIndex = 0;
foreach(var item in target)
if(nowIndex++ == index)
return (T)item;
throw new IndexOutOfRangeException("给定的索引超出了枚举器的范围");
}
/// <summary>
/// 获取此枚举器在给定索引下的值,并且允许在无法找到的情况下使用null返回
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="target"></param>
/// <param name="index"></param>
/// <returns></returns>
public static T SelectIndexOrDefault<T>(this IEnumerable<T> target, int index)
where T : class
{
int nowIndex = 0;
foreach(var item in target)
if(nowIndex++ == index)
return (T)item;
return null;
}
/// <summary>
/// 按顺序获取一个节点的所有父级节点
/// </summary>
/// <param name="trans"></param>
/// <returns></returns>
public static IEnumerable<Transform> GetParents(this Transform trans)
{
Transform target = trans.parent;
while(target != null)
{
yield return target;
target = target.parent;
}
}
/// <summary>
/// 遍历项目中父级内所有子项的差距,并找到第1个差距最大的项目;
/// <code>
/// 具体是先从当前节点向上级找到第一个最少子项数量的节点,
/// 以此为基准,从当前最少数量节点的子集中返回来自项目的父级(或来自项目);
/// 具体是用来在场景中寻找第一个具有标识意义的节点
/// </code>
/// </summary>
/// <param name="trans"></param>
/// <param name="backStep">倒数步骤数,基于基准父级/param>
/// <returns></returns>
[Obsolete("未验证的,谨慎使用")]
public static Transform GetObjectNameInParentsFilterByChildrenMeanDifferen(this Transform trans, int backStep = 1)
{
int minParentIndex = 0;
int index = 0;
int minChildCount = int.MaxValue;
foreach(Transform parent in trans.GetParents())
{
if(parent.childCount < minChildCount)
{
minChildCount = parent.childCount;
minParentIndex = index;
}
index++;
}
return trans.GetParents().SelectIndexOrDefault(minParentIndex - backStep);
}
/// <summary>
/// 获取一个变换节点下所有的子成员
/// </summary>
/// <param name="trans"></param>
/// <param name="recursion">递归深度,0表示仅在第一子集中寻找,1表示在包含下一级在内的所有成员中寻找</param>
/// <returns></returns>
public static IEnumerable<Transform> GetChildren(this Transform trans)
{
@@ -23,34 +106,36 @@ namespace XericLibrary.Runtime.MacroLibrary
}
/// <summary>
/// 在所有子成员中深度优先找到第一个组件
/// 在所有子成员中深度优先找到第一个组件
/// 注意这只会在子项中查找。
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="trans"></param>
/// <param name="recursion">遍历深度,0表示仅在此处寻找,1表示在包含下一级在内的所有成员中寻找</param>
/// <param name="recursion">遍历深度,0表示仅在子集中寻找,1表示在子集中寻找,如果找不到的将在子集的子集中寻找,以此类推</param>
/// <returns></returns>
public static IEnumerable<T> GetChildrenRecursionComponents<T>(this Transform trans, int recursion = 1)
public static IEnumerable<T> GetComponentsInRecursionChildren<T>(this Transform trans, int recursion = 1)
where T : Component
{
int newRecursion = recursion - 1;
foreach(var item in trans.GetChildren())
{
var comp = item.GetComponent<T>();
if(comp == null && newRecursion > 0)
comp = item.GetChildrenRecursionComponent<T>(newRecursion);
comp = item.GetComponentInRecursionChildren<T>(newRecursion);
yield return comp;
}
}
/// <summary>
/// 按深度优先寻找一个组件
/// 按深度优先寻找一个组件
/// 注意这只会在子项中查找。
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="trans"></param>
/// <param name="depth">遍历深度,0表示仅在第一子集中寻找,1表示在包含下一级在内的所有成员中寻找</param>
/// <param name="depth">遍历深度,0表示仅在子集中寻找,1表示在子集中寻找,如果找不到的将在子集的子集中寻找,以此类推</param>
/// <returns></returns>
public static T GetChildrenRecursionComponent<T>(this Transform trans, int depth = 1)
public static T GetComponentInRecursionChildren<T>(this Transform trans, int depth = 1)
where T : Component
{
T result;
@@ -61,7 +146,7 @@ namespace XericLibrary.Runtime.MacroLibrary
{
result = item.GetComponent<T>();
if(result == null && newDepth > 0)
result = item.GetChildrenRecursionComponent<T>(newDepth);
result = item.GetComponentInRecursionChildren<T>(newDepth);
if(result != null)
return result;
}
@@ -125,5 +210,56 @@ namespace XericLibrary.Runtime.MacroLibrary
#endregion
#region 2023/10
/// <summary>
/// 在所有子成员中深度优先找到第一个组件
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="trans"></param>
/// <param name="recursion">遍历深度,0表示仅在此处寻找,1表示在包含下一级在内的所有成员中寻找</param>
/// <returns></returns>
[Obsolete("命名不符合规则,将使用GetComponentsInRecursionChildren替换")]
public static IEnumerable<T> GetChildrenRecursionComponents<T>(this Transform trans, int recursion = 1)
where T : Component
{
int newRecursion = recursion - 1;
foreach(var item in trans.GetChildren())
{
var comp = item.GetComponent<T>();
if(comp == null && newRecursion > 0)
comp = item.GetChildrenRecursionComponent<T>(newRecursion);
yield return comp;
}
}
/// <summary>
/// 按深度优先寻找一个组件
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="trans"></param>
/// <param name="depth">遍历深度,0表示仅在第一子集中寻找,1表示在包含下一级在内的所有成员中寻找</param>
/// <returns></returns>
[Obsolete("命名不符合规则,将使用GetComponentsInRecursionChildren替换")]
public static T GetChildrenRecursionComponent<T>(this Transform trans, int depth = 1)
where T : Component
{
T result;
int newDepth = depth - 1;
foreach(var item in trans.GetChildren())
{
result = item.GetComponent<T>();
if(result == null && newDepth > 0)
result = item.GetChildrenRecursionComponent<T>(newDepth);
if(result != null)
return result;
}
return null;
}
#endregion
}
}
+41 -1
View File
@@ -98,6 +98,7 @@ namespace XericLibrary.Runtime.MacroLibrary
/// 将一个数值转为中文小写格式,并确保读写格式满足日常使用;
/// 比如 510会读成五百一十,9009会读成九千零九,
/// 最大支持到九千亿,理论上并不是它的极限,只要继续套格式即可。
/// 不过缺点是在读10,11时,会读成一十,一十一,需要额外处理一下以符合阅读习惯
/// </summary>
/// <param name="number"></param>
/// <returns></returns>
@@ -110,8 +111,47 @@ namespace XericLibrary.Runtime.MacroLibrary
// 如果为负就在前面加上负
if(number < 0)
guide = "负";
string result;
// 特殊处理
switch(number)
{
case 10:
result = "十";
break;
case 11:
result = "十一";
break;
case 12:
result = "十二";
break;
case 13:
result = "十三";
break;
case 14:
result = "十四";
break;
case 15:
result = "十五";
break;
case 16:
result = "十六";
break;
case 17:
result = "十七";
break;
case 18:
result = "十八";
break;
case 19:
result = "十九";
break;
default:
result = NumberToChinese(Mathf.Abs(number), out var zero);
break;
}
// 合并格式化
return guide + NumberToChinese(Mathf.Abs(number), out var zero);
return guide + result;
}
#endregion