215 lines
6.3 KiB
C#
215 lines
6.3 KiB
C#
|
using System;
|
||
|
using System.Collections;
|
||
|
using System.Collections.Generic;
|
||
|
using System.Linq;
|
||
|
|
||
|
namespace BITKit
|
||
|
{
|
||
|
public static class MathE
|
||
|
{
|
||
|
public static int GetHash<T>(IEnumerable<T> self)
|
||
|
{
|
||
|
var hash = 0;
|
||
|
foreach (var x in self)
|
||
|
{
|
||
|
if (x is not null)
|
||
|
hash += x.GetHashCode();
|
||
|
}
|
||
|
|
||
|
return hash;
|
||
|
}
|
||
|
public static bool IndexInRange<T>(this IEnumerable<T> self, int index)
|
||
|
{
|
||
|
return index >= 0 && index < self.Count();
|
||
|
}
|
||
|
public static bool Equals<T>(params T[] objs)
|
||
|
{
|
||
|
var a = objs.FirstOrDefault();
|
||
|
foreach (var b in objs)
|
||
|
{
|
||
|
if (a.Equals(b))
|
||
|
{
|
||
|
a = b;
|
||
|
continue;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
return false;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return true;
|
||
|
}
|
||
|
public static IEnumerable<T> Subtract<T>(IEnumerable<T> a, IEnumerable<T> b) where T : IEnumerable
|
||
|
{
|
||
|
List<T> list = new();
|
||
|
foreach (var x in a)
|
||
|
{
|
||
|
if (b.Contains(x))
|
||
|
{
|
||
|
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
list.Add(x);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return list;
|
||
|
}
|
||
|
|
||
|
public static bool TryGetIndexOf<T>(this IEnumerable<T> self, Func<T, bool> factory, out int index)
|
||
|
{
|
||
|
index = -1;
|
||
|
var enumerable = self as T[] ?? self.ToArray();
|
||
|
for (var i = 0; i < enumerable.Length; i++)
|
||
|
{
|
||
|
var item = enumerable.ElementAt(i);
|
||
|
if (!factory.Invoke(item)) continue;
|
||
|
index = i;
|
||
|
return true;
|
||
|
}
|
||
|
return false;
|
||
|
}
|
||
|
public static bool Contains<T>(IEnumerable<T> a, IEnumerable<T> b)
|
||
|
{
|
||
|
foreach (var x in b)
|
||
|
{
|
||
|
var enumerable = a as T[] ?? a.ToArray();
|
||
|
if (enumerable.Contains(x))
|
||
|
{
|
||
|
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
return false;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
|
||
|
public static IEnumerable<T[]> Combinations<T>(IEnumerable<T> source)
|
||
|
{
|
||
|
if (null == source) throw new ArgumentNullException(nameof(source));
|
||
|
T[] data = source.ToArray();
|
||
|
return Enumerable.Range(0, 1 << (data.Length) - 1)
|
||
|
.Select(index => data.Where((v, i) => (index & (1 << i)) != 0).ToArray());
|
||
|
}
|
||
|
|
||
|
public static IEnumerable<T> InsertOf<T>(this IEnumerable<T> self, int index, T item)
|
||
|
{
|
||
|
if (self is null) return null;
|
||
|
switch (self)
|
||
|
{
|
||
|
case List<T> list:
|
||
|
list.Insert(index, item);
|
||
|
break;
|
||
|
default:
|
||
|
var _list = self.ToList();
|
||
|
_list.Insert(index, item);
|
||
|
return _list;
|
||
|
}
|
||
|
|
||
|
return self;
|
||
|
}
|
||
|
|
||
|
public static bool TryGetSingle<T>(this IEnumerable<T> self, out T value)
|
||
|
{
|
||
|
value = default;
|
||
|
if (self.Any())
|
||
|
{
|
||
|
value = self.ElementAt(0);
|
||
|
}
|
||
|
|
||
|
return value is not null;
|
||
|
}
|
||
|
|
||
|
/// <summary>
|
||
|
/// 组合集合中的所有元素
|
||
|
/// </summary>
|
||
|
/// <param name="self"></param>
|
||
|
/// <typeparam name="T"></typeparam>
|
||
|
/// <returns></returns>
|
||
|
public static IEnumerable<T> AllCombinations<T>(this IEnumerable<T> self)
|
||
|
{
|
||
|
var list = self.ToList();
|
||
|
var count = list.Count;
|
||
|
for (var i = 0; i < count; i++)
|
||
|
{
|
||
|
var item = list[i];
|
||
|
for (var j = i + 1; j < count; j++)
|
||
|
{
|
||
|
yield return item;
|
||
|
yield return list[j];
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
public static IEnumerable<T> SelectManyPro<T>(this IEnumerable<T> self, Func<T, IEnumerable<T>> factory)
|
||
|
{
|
||
|
return Get(self);
|
||
|
IEnumerable<T> Get(IEnumerable<T> list)
|
||
|
{
|
||
|
var newList = new List<T>();
|
||
|
foreach (var x in list)
|
||
|
{
|
||
|
newList.Add(x);
|
||
|
newList.AddRange(Get(factory.Invoke(x)));
|
||
|
}
|
||
|
|
||
|
return newList.Distinct();
|
||
|
}
|
||
|
}
|
||
|
/// <summary>
|
||
|
/// 获取集合中所有的组合,每个组合中的元素个数为输入集合的元素个数,每个元素只出现一次
|
||
|
/// </summary>
|
||
|
/// <param name="self"></param>
|
||
|
/// <typeparam name="T"></typeparam>
|
||
|
/// <returns></returns>
|
||
|
public static IEnumerable<IEnumerable<T>> GetAllCombination<T>(this IEnumerable<T> self)
|
||
|
{
|
||
|
var list = self.ToList();
|
||
|
var count = list.Count;
|
||
|
for (var i = 0; i < count; i++)
|
||
|
{
|
||
|
var item = list[i];
|
||
|
for (var j = i + 1; j < count; j++)
|
||
|
{
|
||
|
yield return new List<T> { item, list[j] };
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
/// <summary>
|
||
|
/// Linq Distinct扩展方法,可以传入自定义比较器
|
||
|
/// </summary>
|
||
|
/// <param name="source"></param>
|
||
|
/// <param name="comparer"></param>
|
||
|
/// <typeparam name="T"></typeparam>
|
||
|
/// <returns></returns>
|
||
|
public static IEnumerable<T> Distinct<T>(
|
||
|
this IEnumerable<T> source, Func<T, T, bool> comparer)
|
||
|
where T : class
|
||
|
=> source.Distinct(new DynamicEqualityComparer<T>(comparer));
|
||
|
/// <summary>
|
||
|
/// 动态自定义比较器
|
||
|
/// </summary>
|
||
|
/// <typeparam name="T"></typeparam>
|
||
|
private sealed class DynamicEqualityComparer<T> : IEqualityComparer<T>
|
||
|
where T : class
|
||
|
{
|
||
|
private readonly Func<T, T, bool> _func;
|
||
|
|
||
|
public DynamicEqualityComparer(Func<T, T, bool> func)
|
||
|
{
|
||
|
_func = func;
|
||
|
}
|
||
|
|
||
|
public bool Equals(T x, T y) => _func(x, y);
|
||
|
|
||
|
public int GetHashCode(T obj) => 0;
|
||
|
}
|
||
|
}
|
||
|
}
|