Files
懒得勤快 8e10f5f1bd 精简代码
2023-12-08 23:49:54 +08:00

64 lines
1.7 KiB
C#

using System;
using System.Collections.Generic;
using System.Linq;
namespace Masuit.Tools.RandomSelector;
internal abstract class SelectorBase<T>
{
protected readonly WeightedSelector<T> WeightedSelector;
internal SelectorBase(WeightedSelector<T> weightedSelector)
{
WeightedSelector = weightedSelector;
}
/// <summary>
/// 执行二进制筛选
/// </summary>
internal WeightedItem<T> BinarySelect(List<WeightedItem<T>> items)
{
if (items.Count == 0)
{
throw new InvalidOperationException("没有元素可以筛选");
}
int index = Array.BinarySearch(WeightedSelector.CumulativeWeights, new Random().Next(1, items.Sum(i => i.Weight) + 1));
//如果存在接近的匹配项,二进制搜索返回的负数会比搜索的第1个索引少1。
if (index < 0)
{
index = -index - 1;
}
return items[index];
}
/// <summary>
/// 线性筛选
/// </summary>
/// <param name="items"></param>
/// <returns></returns>
internal WeightedItem<T> LinearSelect(List<WeightedItem<T>> items)
{
// 只对具有允许重复项的多选功能有用,它会随着时间从列表中删除项目。 在这些条件下没有消耗更多性能让二进制搜索起作用。
if (!items.Any())
{
return new WeightedItem<T>(default, 0);
}
var count = 0;
var seed = new Random().Next(1, items.Sum(i => i.Weight) + 1);
foreach (var item in items)
{
count += item.Weight;
if (seed <= count)
{
return item;
}
}
return items.FirstOrDefault();
}
}