393 lines
8.3 KiB
TypeScript
393 lines
8.3 KiB
TypeScript
|
export class List<Item> extends Array<Item>
|
||
|
{
|
||
|
/** 返回符合条件的第一个元素 */
|
||
|
first(fn: (item: Item) => boolean): Item
|
||
|
{
|
||
|
if (this.length == 0)
|
||
|
return null
|
||
|
for (const item of this)
|
||
|
{
|
||
|
if (fn(item))
|
||
|
return item
|
||
|
}
|
||
|
return null
|
||
|
}
|
||
|
|
||
|
/** 返回符合条件的最后一元素 */
|
||
|
last(fn: (t: Item) => boolean): Item
|
||
|
{
|
||
|
if (this.length == 0)
|
||
|
return null
|
||
|
for (let i = this.length - 1; i >= 0; i--)
|
||
|
{
|
||
|
if (fn(this[i]))
|
||
|
return this[i]
|
||
|
}
|
||
|
return null
|
||
|
}
|
||
|
|
||
|
/** 最大值 */
|
||
|
max<T>(fn: (item: Item) => T): T
|
||
|
{
|
||
|
let maxV: T
|
||
|
for (const i of this)
|
||
|
{
|
||
|
let v = fn(i)
|
||
|
if (maxV == null)
|
||
|
{
|
||
|
maxV = fn(i)
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
if (v > maxV)
|
||
|
{
|
||
|
maxV = v
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
return maxV
|
||
|
}
|
||
|
|
||
|
/** 最小值 */
|
||
|
min<T>(fn: (item: Item) => T): T
|
||
|
{
|
||
|
let minV: T
|
||
|
for (const i of this)
|
||
|
{
|
||
|
let v = fn(i)
|
||
|
if (minV == null)
|
||
|
{
|
||
|
minV = fn(i)
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
if (v < minV)
|
||
|
{
|
||
|
minV = v
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
return minV
|
||
|
}
|
||
|
|
||
|
/** 累加 */
|
||
|
sum(fn: (item: Item) => number): number
|
||
|
{
|
||
|
let v: number = 0
|
||
|
for (const t of this)
|
||
|
{
|
||
|
v = v + fn(t)
|
||
|
}
|
||
|
return v
|
||
|
}
|
||
|
|
||
|
/** 平均值 */
|
||
|
avg(fn: (item: Item) => number): number
|
||
|
{
|
||
|
if (this.length == 0)
|
||
|
return 0
|
||
|
let sum = this.sum(fn)
|
||
|
return sum / this.length
|
||
|
}
|
||
|
|
||
|
/** 满足条件的元素数量 */
|
||
|
count(fn: (item: Item) => number): number
|
||
|
{
|
||
|
if (this.length == 0)
|
||
|
return 0
|
||
|
let c = 0
|
||
|
for (const item of this)
|
||
|
{
|
||
|
if (fn(item))
|
||
|
c = c + 1
|
||
|
}
|
||
|
return c
|
||
|
}
|
||
|
|
||
|
FindMax<T>(fn: (item: Item) => T): Item
|
||
|
{
|
||
|
return this.reduce((a: Item, b: Item): Item => fn(a) > fn(b) ? a : b)
|
||
|
}
|
||
|
}
|
||
|
|
||
|
export class ArrayExt
|
||
|
{
|
||
|
/** 返回满足条件的元素数量 */
|
||
|
static count<Item>(list: Item[], fn: (item: Item) => boolean): number
|
||
|
{
|
||
|
if (list.length == 0)
|
||
|
return 0
|
||
|
let c = 0
|
||
|
for (const item of list)
|
||
|
{
|
||
|
if (fn(item))
|
||
|
c = c + 1
|
||
|
}
|
||
|
return c
|
||
|
}
|
||
|
|
||
|
/** 移除 */
|
||
|
static remove<Item>(list: Item[], obj: Item)
|
||
|
{
|
||
|
let index = list.findIndex(t => t == obj)
|
||
|
if (index == -1)
|
||
|
return
|
||
|
list.splice(index, 1)
|
||
|
}
|
||
|
|
||
|
/** 返回符合条件的第一个元素 */
|
||
|
static first<Item>(list: Item[], fn: (item: Item) => boolean, orderFn1: (item: Item) => number = null, orderFn2: (item: Item) => number = null): Item
|
||
|
{
|
||
|
if (list.length == 0)
|
||
|
return null
|
||
|
if (orderFn1 == null)
|
||
|
{
|
||
|
for (const item of list)
|
||
|
{
|
||
|
if (fn(item))
|
||
|
return item
|
||
|
}
|
||
|
return null
|
||
|
}
|
||
|
|
||
|
let minValue1: number
|
||
|
let minValue2: number
|
||
|
let minItem: Item
|
||
|
for (const item of list)
|
||
|
{
|
||
|
if (fn(item) == false)
|
||
|
continue
|
||
|
let v1 = orderFn1(item)
|
||
|
let v2 = orderFn2 != null ? orderFn2(item) : 0
|
||
|
if (minValue1 == null || v1 < minValue1 || (v1 == minValue1 && v2 < minValue2))
|
||
|
{
|
||
|
minValue1 = v1
|
||
|
minValue2 = v2
|
||
|
minItem = item
|
||
|
}
|
||
|
}
|
||
|
return minItem
|
||
|
}
|
||
|
|
||
|
/** 返回符合条件的最后一元素 */
|
||
|
static last<Item>(list: Item[], fn: (t: Item) => boolean, orderFn1: (item: Item) => number = null, orderFn2: (item: Item) => number = null): Item
|
||
|
{
|
||
|
if (list.length == 0)
|
||
|
return null
|
||
|
if (orderFn1 == null)
|
||
|
{
|
||
|
for (let i = list.length - 1; i >= 0; i--)
|
||
|
{
|
||
|
if (fn(list[i]))
|
||
|
return list[i]
|
||
|
}
|
||
|
return null
|
||
|
}
|
||
|
|
||
|
//
|
||
|
let maxValue1: number
|
||
|
let maxValue2: number
|
||
|
let maxItem: Item
|
||
|
for (const item of list)
|
||
|
{
|
||
|
if (fn(item) == false)
|
||
|
continue
|
||
|
let v1 = orderFn1(item)
|
||
|
let v2 = orderFn2 ? orderFn2(item) : 0
|
||
|
if (maxValue1 == null || v1 > maxValue1 || (v1 == maxValue1 && v2 > maxValue2))
|
||
|
{
|
||
|
maxValue1 = v1
|
||
|
maxValue2 = v2
|
||
|
maxItem = item
|
||
|
}
|
||
|
}
|
||
|
return maxItem
|
||
|
}
|
||
|
|
||
|
/** 取最大值 */
|
||
|
static max<T1, T2>(list: T1[], fn: (item: T1) => T2, whereF: (item: T1) => boolean = null, defaultV: T2 = null): T2
|
||
|
{
|
||
|
let maxV: T2
|
||
|
for (const i of list)
|
||
|
{
|
||
|
if (whereF && whereF(i) == false)
|
||
|
continue
|
||
|
let v = fn(i)
|
||
|
if (maxV == undefined)
|
||
|
{
|
||
|
maxV = fn(i)
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
if (v > maxV)
|
||
|
{
|
||
|
maxV = v
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
if (maxV != undefined)
|
||
|
return maxV
|
||
|
return defaultV
|
||
|
}
|
||
|
|
||
|
/** 最小值 */
|
||
|
static min<Item, T>(list: Item[], fn: (item: Item) => T, whereF: (item: Item) => boolean = null, defaultV: T = null): T
|
||
|
{
|
||
|
let minV: T
|
||
|
for (const i of list)
|
||
|
{
|
||
|
if (whereF && whereF(i) == false)
|
||
|
continue
|
||
|
let v = fn(i)
|
||
|
if (minV == undefined)
|
||
|
{
|
||
|
minV = v
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
if (v < minV)
|
||
|
{
|
||
|
minV = v
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
if (minV != undefined)
|
||
|
return minV
|
||
|
return defaultV
|
||
|
}
|
||
|
|
||
|
/** 累加 */
|
||
|
static sum<Item>(list: Item[], fn: (item: Item) => number, wn?: (item: Item) => boolean): number
|
||
|
{
|
||
|
let v: number = 0
|
||
|
for (const t of list)
|
||
|
{
|
||
|
if (wn && wn(t) == false)
|
||
|
continue
|
||
|
v = v + fn(t)
|
||
|
}
|
||
|
return v
|
||
|
}
|
||
|
|
||
|
/** 平均值 */
|
||
|
static avg<Item>(list: Item[], fn: (item: Item) => number): number
|
||
|
{
|
||
|
if (this.length == 0)
|
||
|
return 0
|
||
|
let sum = ArrayExt.sum(list, fn)
|
||
|
return sum / this.length
|
||
|
}
|
||
|
|
||
|
/** 排序 */
|
||
|
static sortBy<Item>(list: Item[], fn: (item: Item) => number, fn2: (item: Item) => number = null)
|
||
|
{
|
||
|
if (fn2 == null)
|
||
|
return list.sort((a: Item, b: Item): number => fn(a) - fn(b))
|
||
|
else
|
||
|
return list.sort((a: Item, b: Item): number => fn(a) == fn(b) ? (fn2(a) - fn2(b)) : fn(a) - fn(b))
|
||
|
}
|
||
|
|
||
|
/** 降序 排序 */
|
||
|
static sortByDescending<Item>(list: Item[], fn: (item: Item) => number)
|
||
|
{
|
||
|
list.sort((a: Item, b: Item): number => fn(b) - fn(a))
|
||
|
}
|
||
|
|
||
|
/** 排序成新的数组 */
|
||
|
static orderBy<Item>(list: Item[], fn: (item: Item) => number, fn2: (item: Item) => number = null): Item[]
|
||
|
{
|
||
|
let newList = list.concat([])
|
||
|
if (fn2 == null)
|
||
|
return newList.sort((a: Item, b: Item): number => fn(a) - fn(b))
|
||
|
else
|
||
|
return newList.sort((a: Item, b: Item): number => fn(a) == fn(b) ? (fn2(a) - fn2(b)) : fn(a) - fn(b))
|
||
|
}
|
||
|
|
||
|
/** 降序成新的数组 */
|
||
|
static orderByDescending<Item>(list: Item[], fn: (item: Item) => number, fn2: (item: Item) => number = null): Item[]
|
||
|
{
|
||
|
let newList = list.concat([])
|
||
|
if (fn2 == null)
|
||
|
return list.sort((a: Item, b: Item): number => fn(b) - fn(a))
|
||
|
else
|
||
|
return list.sort((a: Item, b: Item): number => fn(a) == fn(b) ? (fn2(b) - fn2(a)) : fn(b) - fn(a))
|
||
|
}
|
||
|
|
||
|
/** 分组 */
|
||
|
static groupBy<Item, gT>(list: Item[], fn: (item: Item) => gT): GroupItem<gT, Item>[]
|
||
|
{
|
||
|
let groups = new Array<GroupItem<gT, Item>>()
|
||
|
|
||
|
for (const item of list)
|
||
|
{
|
||
|
let key = fn(item)
|
||
|
let group = groups.find(t => t.key == key)
|
||
|
if (group == null)
|
||
|
{
|
||
|
group = new GroupItem(key)
|
||
|
groups.push(group)
|
||
|
}
|
||
|
group.push(item)
|
||
|
}
|
||
|
return groups
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* 选择
|
||
|
* let newObjectList = ArrayExt.Select(list,t=>({pA:t.name, pB:t.age + "_"+ t.month}) ) ;
|
||
|
*/
|
||
|
static Select<Item, rT>(list: Item[], fn: (item: Item) => rT): rT[]
|
||
|
{
|
||
|
let newList = new Array<rT>()
|
||
|
for (const t of list)
|
||
|
{
|
||
|
newList.push(fn(t))
|
||
|
}
|
||
|
return newList
|
||
|
}
|
||
|
|
||
|
/** 过来,并按顺序排序 */
|
||
|
static where<Item>(list: Item[], whereFn: (item: Item) => boolean, orderfn1: (item: Item) => number = null, orderfn2: (item: Item) => number = null): Item[]
|
||
|
{
|
||
|
let newList = list.filter(whereFn)
|
||
|
if (orderfn1 == null && orderfn2 == null)
|
||
|
return newList
|
||
|
return ArrayExt.sortBy(newList, orderfn1, orderfn2)
|
||
|
}
|
||
|
}
|
||
|
|
||
|
export class GroupItem<gT, Item>
|
||
|
{
|
||
|
key: gT
|
||
|
get count() { return this.list.length }
|
||
|
list: Item[]
|
||
|
|
||
|
constructor(k: gT)
|
||
|
{
|
||
|
this.key = k
|
||
|
this.list = []
|
||
|
}
|
||
|
|
||
|
push(d: Item)
|
||
|
{
|
||
|
this.list.push(d)
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* 对排序好的数组进行去重操作
|
||
|
* @param {(e1, e2) => boolean} [checkFuction] 校验对象相等函数
|
||
|
* @returns {Array<T>} 返回自身
|
||
|
*/
|
||
|
export function arrayRemoveDuplicateBySort<T>(arr: Array<T>, checkFuction: (e1: T, e2: T) => boolean = checkEqual): Array<T>
|
||
|
{
|
||
|
if (arr.length < 2)
|
||
|
return arr
|
||
|
let j = 1
|
||
|
for (let i = 1, l = arr.length; i < l; i++)
|
||
|
if (!checkFuction(arr[j - 1], arr[i]))
|
||
|
arr[j++] = arr[i]
|
||
|
arr.length = j
|
||
|
return arr
|
||
|
}
|