You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

313 lines
10 KiB

using System;
using System.Collections;
using System.Collections.Generic;
using System.Text;
namespace Apewer.Internals
{
internal class CollectionHelper
{
#region 排序。
public static List<T> Sort<T>(List<T> list, Func<T, T, int> comparison)
{
if (list == null) return null;
if (comparison == null) return list;
list.Sort(new Comparison<T>(comparison));
return list;
}
public static List<T> Ascend<T>(List<T> list) where T : IComparable<T>
{
if (list == null) return null;
list.Sort((a, b) => a.CompareTo(b));
return list;
}
public static List<T> Descend<T>(List<T> list) where T : IComparable<T>
{
if (list == null) return null;
list.Sort((a, b) => -a.CompareTo(b));
return list;
}
public static Dictionary<TKey, TValue> SortKey<TKey, TValue>(Dictionary<TKey, TValue> dict, Func<TKey, TKey, int> comparison)
{
if (dict == null) return null;
if (comparison == null) return null;
var list = new List<KeyValuePair<TKey, TValue>>(dict);
list.Sort(new Comparison<KeyValuePair<TKey, TValue>>((a, b) => comparison(a.Key, b.Key)));
dict.Clear();
foreach (var item in list) dict.Add(item.Key, item.Value);
return dict;
}
public static Dictionary<TKey, TValue> SortValue<TKey, TValue>(Dictionary<TKey, TValue> dict, Func<TValue, TValue, int> comparison)
{
if (dict == null) return null;
if (comparison == null) return dict;
var list = new List<KeyValuePair<TKey, TValue>>(dict);
list.Sort(new Comparison<KeyValuePair<TKey, TValue>>((a, b) => comparison(a.Value, b.Value)));
dict.Clear();
foreach (var item in list) dict.Add(item.Key, item.Value);
return dict;
}
#endregion
public static T First<T>(IEnumerable<T> collection, T failed = default(T))
{
if (collection == null) return failed;
var array = collection as T[];
if (array != null) return array.Length > 0 ? array[0] : failed;
var list = collection as IList<T>;
if (list != null) return list.Count > 0 ? list[0] : failed;
foreach (var item in collection) return item;
return failed;
}
public static T Last<T>(IEnumerable<T> collection, T failed = default(T))
{
if (collection == null) return failed;
var array = collection as T[];
if (array != null) return array.Length > 0 ? array[array.Length - 1] : failed;
var list = collection as IList<T>;
if (list != null) return list.Count > 0 ? list[list.Count - 1] : failed;
var value = failed;
foreach (var item in collection) value = item;
return value;
}
// 安全转换为 List<T> 对象。可指定排除 NULL 值元素。
public static List<T> ToList<T>(IEnumerable<T> objects, bool excludeNull = false)
{
if (objects == null) return new List<T>();
var list = new List<T>();
var collection = objects as ICollection;
if (collection != null)
{
list.AddRange(objects);
}
else
{
var group = 1024;
var added = 0;
var capacity = 0;
if (objects != null)
{
foreach (var item in objects)
{
if (excludeNull && item == null) continue;
if (added == capacity)
{
capacity += group;
list.Capacity = capacity;
}
list.Add(item);
added += 1;
}
}
list.Capacity = added;
}
return list;
}
// 安全转换为 T[] 对象。可指定排除 NULL 值元素。
public static T[] ToArray<T>(IEnumerable<T> objects, bool excludeNull = false)
{
if (objects == null) return new T[0];
if (objects is T[]) return (T[])objects;
var collection = objects as ICollection;
if (collection != null)
{
var array = new T[collection.Count];
collection.CopyTo(array, 0);
return array;
}
else
{
var group = 1024;
var array = new T[group];
var added = 0;
var capacity = 0;
foreach (var item in objects)
{
if (excludeNull && item == null) continue;
if (added == capacity)
{
capacity += group;
var temp = new T[capacity];
Array.Copy(array, 0, temp, 0, added);
array = temp;
}
array[added] = item;
added += 1;
}
if (added < 1 || added == capacity) return array;
var collapsed = new T[added];
Array.Copy(array, 0, collapsed, 0, added);
return collapsed;
}
}
public static bool IsEmpty<T>(IEnumerable<T> objects)
{
if (objects == null) return true;
if (objects is T[]) return ((T[])objects).LongLength == 0;
if (objects is ICollection<T>) return ((ICollection<T>)objects).Count == 0;
foreach (var i in objects) return false;
return true;
}
public static bool NotEmpty<T>(IEnumerable<T> objects) => !IsEmpty<T>(objects);
// 判断集合包含特定值。
public static bool Contains<T>(IEnumerable<T> objects, T cell)
{
if (objects == null) return false;
// objects 实现了含有 Contains 方法的接口。
if (objects is ICollection<T>) return ((ICollection<T>)objects).Contains(cell);
// cell 无效。
if (cell == null)
{
foreach (var i in objects)
{
if (i == null) return true;
}
return false;
}
// cell 有效,进行默认比较。
var comparer = EqualityComparer<T>.Default;
foreach (var i in objects)
{
if (comparer.Equals(i, cell)) return true;
}
return false;
}
// 获取集合中元素的数量。
public static int Count<T>(IEnumerable<T> objects)
{
if (objects == null) return 0;
var array = objects as T[];
if (array != null) return array.Length;
var collection = objects as ICollection<T>;
if (collection != null) return collection.Count;
var count = 0;
foreach (var cell in objects) count++;
return count;
}
// 对元素去重,且去除 NULL 值。
public static T[] Distinct<T>(IEnumerable<T> items)
{
if (items == null) throw new ArgumentNullException(nameof(items));
var count = Count(items);
var added = 0;
var array = new T[count];
var comparer = EqualityComparer<T>.Default;
foreach (var item in items)
{
if (item == null) continue;
var contains = false;
foreach (var i in array)
{
if (comparer.Equals(i, item))
{
contains = true;
break;
}
}
if (contains) continue;
array[added] = item;
added++;
}
if (added < count)
{
var temp = new T[added];
Array.Copy(array, 0, temp, 0, added);
array = temp;
}
return array;
}
// 获取可枚举集合的部分元素。
public static T[] Slice<T>(IEnumerable<T> objects, int skip = 0, int count = -1, Func<T> stuffer = null)
{
if (count == 0) return new T[0];
var ab = new ArrayBuilder<T>();
var added = 0;
if (skip < 0)
{
var end = 0 - skip;
for (var i = 0; i < end; i++)
{
ab.Add(stuffer == null ? default : stuffer());
added++;
if (count > 0 && added == count) return ab.Export();
}
}
if (objects != null)
{
var offset = 0;
foreach (var item in objects)
{
if (offset < skip)
{
offset++;
continue;
}
ab.Add(item);
added++;
offset++;
if (count > 0 && added == count) return ab.Export();
}
}
while (added < count)
{
ab.Add(stuffer == null ? default : stuffer());
added++;
}
return ab.Export();
}
public static IList<T> Add<T>(IList<T> list, IEnumerable<T> items)
{
if (list != null && items != null)
{
foreach (var item in items) list.Add(item);
}
return list;
}
public static bool Add<TKey, TValue>(IList<KeyValuePair<TKey, TValue>> list, TKey key, TValue value)
{
if (list == null) return false;
list.Add(new KeyValuePair<TKey, TValue>(key, value));
return true;
}
}
}