This repository has been archived on 2025-09-23. You can view files and clone it. You cannot open issues or pull requests or push a commit.
Files
XericLibrary-OLD/Runtime/MicroLibrary/MacroList.cs
LiRuoChen a658cc424b 添加了更多的材质函数,部分与引擎新特性重合,这是为了能够脱离引擎在多个版本中更具可移植性。
添加了多种对程序流程控制与保全的脚本,而且现在可以更快速的构建一个具有线性关系的协程了。
  添加了一个支持多种模式的单维梯度控制器,类似unity的颜色梯度类型。
  添加了一个用于看向某个物体的旋转控制器。
  添加了一个加载宏。
  完善了批处理脚本流程。
2023-11-23 11:10:40 +08:00

151 lines
3.8 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
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);
/// 缺点是元素0很大概率会在最后出现
/// </summary>
/// <param name="length">待选项目的索引长度</param>
/// <param name="select">输出项目的索引长度</param>
/// <returns></returns>
public static List<int> FisherYatesShuffle(int length, int select)
{
if(select > length)
throw new ArgumentOutOfRangeException("在进行洗牌时,要求输出的项目比拥有的项目更多,这是不合理的。");
var random = new System.Random();
List<int> arr = Enumerable.Range(0, 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="length"></param>
/// <param name="select"></param>
/// <param name="repet"></param>
/// <returns></returns>
public static List<int> FisherYatesShuffle(int length, int select, int repet)
{
if(select > length)
throw new ArgumentOutOfRangeException("在进行洗牌时,要求输出的项目比拥有的项目更多,这是不合理的。");
#if UNITY_EDITOR
if(repet > 100)
Debug.LogError("洗牌的重复次数太高(> 100),已限制数量");
#endif
repet = Math.Clamp(repet, 1, 100);
var random = new System.Random();
List<int> arr = Enumerable.Range(0, length).ToList();
List<int> res = new List<int>();
for(int j = 0; j < repet; j++)
{
for(int i = 0; i < length; i++)
{
int k = random.Next(arr.Count);
res.Add(arr[k]);
arr.RemoveAt(k);
}
arr = res.ToList();
res.Clear();
}
return arr;
}
/// <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
#region
/// <summary>
/// 获取列表中随机顺序的对象
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="list"></param>
/// <param name="count">需要采样的数量</param>
/// <returns></returns>
public static IEnumerable<T> GetRandom<T>(this List<T> list, int count = -1)
{
var index = FisherYatesShuffle(list.Count, count <= 0 ? list.Count : count);
for(int i = 0; i < index.Count; i++)
yield return list[index[i]];
}
#endregion
}
}