260 lines
7.8 KiB
C#
260 lines
7.8 KiB
C#
using NetWorkHelper.ICollections;
|
||
using System;
|
||
using System.Collections.Generic;
|
||
|
||
namespace NetWorkHelper.Helper
|
||
{
|
||
public static class CollectionHelper
|
||
{
|
||
#region Find
|
||
/// <summary>
|
||
/// Find 从集合中选取符合条件的元素
|
||
/// </summary>
|
||
public static List<TObject> Find<TObject>(IEnumerable<TObject> source, Predicate<TObject> predicate)
|
||
{
|
||
List<TObject> list = new List<TObject>();
|
||
CollectionHelper.ActionOnSpecification(source, delegate (TObject ele) { list.Add(ele); }, predicate);
|
||
return list;
|
||
}
|
||
#endregion
|
||
|
||
#region FindFirstSpecification
|
||
/// <summary>
|
||
/// FindFirstSpecification 返回符合条件的第一个元素
|
||
/// </summary>
|
||
public static TObject FindFirstSpecification<TObject>(IEnumerable<TObject> source, Predicate<TObject> predicate)
|
||
{
|
||
foreach (TObject element in source)
|
||
{
|
||
if (predicate(element))
|
||
{
|
||
return element;
|
||
}
|
||
}
|
||
|
||
return default(TObject);
|
||
}
|
||
#endregion
|
||
|
||
#region ContainsSpecification
|
||
/// <summary>
|
||
/// ContainsSpecification 集合中是否包含满足predicate条件的元素。
|
||
/// </summary>
|
||
public static bool ContainsSpecification<TObject>(IEnumerable<TObject> source, Predicate<TObject> predicate, out TObject specification)
|
||
{
|
||
specification = default(TObject);
|
||
foreach (TObject element in source)
|
||
{
|
||
if (predicate(element))
|
||
{
|
||
specification = element;
|
||
return true;
|
||
}
|
||
}
|
||
|
||
return false;
|
||
}
|
||
|
||
/// <summary>
|
||
/// ContainsSpecification 集合中是否包含满足predicate条件的元素。
|
||
/// </summary>
|
||
public static bool ContainsSpecification<TObject>(IEnumerable<TObject> source, Predicate<TObject> predicate)
|
||
{
|
||
TObject specification;
|
||
return CollectionHelper.ContainsSpecification<TObject>(source, predicate, out specification);
|
||
}
|
||
#endregion
|
||
|
||
#region ActionOnSpecification
|
||
/// <summary>
|
||
/// ActionOnSpecification 对集合中满足predicate条件的元素执行action。如果没有条件,predicate传入null。
|
||
/// </summary>
|
||
public static void ActionOnSpecification<TObject>(IEnumerable<TObject> collection, Action<TObject> action, Predicate<TObject> predicate)
|
||
{
|
||
if (collection == null)
|
||
{
|
||
return;
|
||
}
|
||
|
||
if (predicate == null)
|
||
{
|
||
foreach (TObject obj in collection)
|
||
{
|
||
action(obj);
|
||
}
|
||
|
||
return;
|
||
}
|
||
|
||
foreach (TObject obj in collection)
|
||
{
|
||
if (predicate(obj))
|
||
{
|
||
action(obj);
|
||
}
|
||
}
|
||
}
|
||
#endregion
|
||
|
||
#region ActionOnEach
|
||
/// <summary>
|
||
/// ActionOnEach 对集合中的每个元素执行action。
|
||
/// </summary>
|
||
public static void ActionOnEach<TObject>(IEnumerable<TObject> collection, Action<TObject> action)
|
||
{
|
||
CollectionHelper.ActionOnSpecification<TObject>(collection, action, null);
|
||
}
|
||
#endregion
|
||
|
||
#region GetPart
|
||
public static T[] GetPart<T>(T[] ary, int startIndex, int count)
|
||
{
|
||
return CollectionHelper.GetPart<T>(ary, startIndex, count, false);
|
||
}
|
||
|
||
public static T[] GetPart<T>(T[] ary, int startIndex, int count, bool reverse)
|
||
{
|
||
if (startIndex >= ary.Length)
|
||
{
|
||
return null;
|
||
}
|
||
|
||
if (ary.Length < startIndex + count)
|
||
{
|
||
count = ary.Length - startIndex;
|
||
}
|
||
|
||
T[] result = new T[count];
|
||
|
||
if (!reverse)
|
||
{
|
||
for (int i = 0; i < count; i++)
|
||
{
|
||
result[i] = ary[startIndex + i];
|
||
}
|
||
}
|
||
else
|
||
{
|
||
for (int i = 0; i < count; i++)
|
||
{
|
||
result[i] = ary[ary.Length - startIndex - 1 - i];
|
||
}
|
||
}
|
||
|
||
return result;
|
||
}
|
||
#endregion
|
||
|
||
#region BinarySearch
|
||
/// <summary>
|
||
/// BinarySearch 从已排序的列表中,采用二分查找找到目标在列表中的位置。
|
||
/// 如果刚好有个元素与目标相等,则返回true,且minIndex会被赋予该元素的位置;否则,返回false,且minIndex会被赋予比目标小且最接近目标的元素的位置
|
||
/// </summary>
|
||
public static bool BinarySearch<T>(IList<T> sortedList, T target, out int minIndex) where T : IComparable
|
||
{
|
||
if (target.CompareTo(sortedList[0]) == 0)
|
||
{
|
||
minIndex = 0;
|
||
return true;
|
||
}
|
||
|
||
if (target.CompareTo(sortedList[0]) < 0)
|
||
{
|
||
minIndex = -1;
|
||
return false;
|
||
}
|
||
|
||
if (target.CompareTo(sortedList[sortedList.Count - 1]) == 0)
|
||
{
|
||
minIndex = sortedList.Count - 1;
|
||
return true;
|
||
}
|
||
|
||
if (target.CompareTo(sortedList[sortedList.Count - 1]) > 0)
|
||
{
|
||
minIndex = sortedList.Count - 1;
|
||
return false;
|
||
}
|
||
|
||
int targetPosIndex = -1;
|
||
int left = 0;
|
||
int right = sortedList.Count - 1;
|
||
|
||
while (right - left > 1)
|
||
{
|
||
int middle = (left + right) / 2;
|
||
|
||
if (target.CompareTo(sortedList[middle]) == 0)
|
||
{
|
||
minIndex = middle;
|
||
return true;
|
||
}
|
||
|
||
if (target.CompareTo(sortedList[middle]) < 0)
|
||
{
|
||
right = middle;
|
||
}
|
||
else
|
||
{
|
||
left = middle;
|
||
}
|
||
}
|
||
|
||
minIndex = left;
|
||
return false;
|
||
}
|
||
#endregion
|
||
|
||
#region GetIntersection 、GetUnion
|
||
/// <summary>
|
||
/// GetIntersection 高效地求两个List元素的交集。
|
||
/// </summary>
|
||
public static List<T> GetIntersection<T>(List<T> list1, List<T> list2) where T : IComparable
|
||
{
|
||
List<T> largList = list1.Count > list2.Count ? list1 : list2;
|
||
List<T> smallList = largList == list1 ? list2 : list1;
|
||
|
||
largList.Sort();
|
||
|
||
int minIndex = 0;
|
||
|
||
List<T> result = new List<T>();
|
||
foreach (T tmp in smallList)
|
||
{
|
||
if (CollectionHelper.BinarySearch<T>(largList, tmp, out minIndex))
|
||
{
|
||
result.Add(tmp);
|
||
}
|
||
}
|
||
|
||
return result;
|
||
}
|
||
|
||
/// <summary>
|
||
/// GetUnion 高效地求两个List元素的并集。
|
||
/// </summary>
|
||
public static List<T> GetUnion<T>(List<T> list1, List<T> list2)
|
||
{
|
||
SortedDictionary<T, int> result = new SortedDictionary<T, int>();
|
||
foreach (T tmp in list1)
|
||
{
|
||
if (!result.ContainsKey(tmp))
|
||
{
|
||
result.Add(tmp, 0);
|
||
}
|
||
}
|
||
|
||
foreach (T tmp in list2)
|
||
{
|
||
if (!result.ContainsKey(tmp))
|
||
{
|
||
result.Add(tmp, 0);
|
||
}
|
||
}
|
||
|
||
return (List<T>)CollectionConverter.CopyAllToList<T>(result.Keys);
|
||
}
|
||
#endregion
|
||
}
|
||
}
|