JavaScript中,实现数组 sum/avg/min/max

2026-01-27 12:27:22  阅读 94 次 评论 0 条

JavaScript中实现类似于Java 的 数组操作

直接上代码(TypeScript写法)

/**
 * ArrayAgg - 数据组合工具
 * https://www.yangguangdream.com/?id=2269
 * 
 * 
 * 用法:
 * ArrayAgg.of(list).mapToInt(x => x.price * x.count).sum()
 * ArrayAgg.of(list).sumBy(x => x.count)
 * ArrayAgg.of(list).count(x => x.count > 0)
 * ArrayAgg.of(list).anyMatch(x => x.count > 0)
 * ArrayAgg.of(list).allMatch(x => x.count > 0)
 * ArrayAgg.of(list).mapToInt(x => x.count).sum()
 * ArrayAgg.of(list).mapToInt(x => x.count).count()
 * ArrayAgg.of(list).mapToInt(x => x.count).avg()
 * ArrayAgg.of(list).mapToInt(x => x.count).min()
 * ArrayAgg.of(list).mapToInt(x => x.count).max()
 */
export class ArrayAgg<T> {
  private readonly arr: readonly T[];

  private constructor(arr: readonly T[]) {
    this.arr = arr ?? [];
  }
  //实例化
  static of<T>(arr: readonly T[] | null | undefined): ArrayAgg<T> {
    return new ArrayAgg<T>(arr ?? []);
  }

  //就是类似Java里面的mapToInt,返回IntAgg对象(数字聚合器,用来进行计算)
  mapToInt(selector: (item: T, index: number) => number): IntAgg {
    const nums = this.arr.map((it, i) => selector(it, i));
    return new IntAgg(nums);
  }

  //直接对对象数组按字段求和:sumBy(x => x.xxx)
  sumBy(selector: (item: T, index: number) => number): number {
    return this.mapToInt(selector).sum();
  }

  //直接计数(可选predicate过滤)
  count(predicate?: (item: T, index: number) => boolean): number {
    if (!predicate) return this.arr.length;
    let c = 0;
    for (let i = 0; i < this.arr.length; i++) if (predicate(this.arr[i], i)) c++;
    return c;
  }

  //anyMatch:是否存在任意一个元素满足条件 ,类似于 Array.some()
  anyMatch(predicate: (item: T, index: number) => boolean): boolean {
    for (let i = 0; i < this.arr.length; i++) if (predicate(this.arr[i], i)) return true;
    return false;
  }
  //allMatch:是否所有元素都满足条件,类似于 Array.every()
  allMatch(predicate: (item: T, index: number) => boolean): boolean {
    for (let i = 0; i < this.arr.length; i++) if (!predicate(this.arr[i], i)) return false;
    return true;
  }
}

//数字聚合器类:sum/avg/min/max
export class IntAgg {
  private readonly nums: readonly number[];

  constructor(nums: readonly number[]) {
    this.nums = nums ?? [];
  }

  //mapToInt(xxx).sum() 求和
  sum(): number {
    let s = 0;
    for (let i = 0; i < this.nums.length; i++) {
      const n = this.nums[i];
      // 忽略 NaN / Infinity(按你需要也可以改成 throw)
      if (Number.isFinite(n)) s += n;
    }
    return s;
  }
  //mapToInt(xxx).count() 计数
  count(): number {
    return this.nums.length;
  }
  //mapToInt(xxx).avg() 平均值
  avg(): number {
    const c = this.count();
    return c === 0 ? 0 : this.sum() / c;
  }
  //mapToInt(xxx).min() 最小值
  min(): number | undefined {
    let m: number | undefined = undefined;
    for (const n of this.nums) {
      if (!Number.isFinite(n)) continue;
      if (m === undefined || n < m) m = n;
    }
    return m;
  }

  //mapToInt(xxx).max() 最大值
  max(): number | undefined {
    let m: number | undefined = undefined;
    for (const n of this.nums) {
      if (!Number.isFinite(n)) continue;
      if (m === undefined || n > m) m = n;
    }
    return m;
  }
}


微信扫码查看本文
本文地址:https://www.yangguangdream.com/?id=2269
版权声明:本文为原创文章,版权归 编辑君 所有,欢迎分享本文,转载请保留出处!
NEXT:已经是最新一篇了

发表评论


表情

还没有留言,还不快点抢沙发?