Skip to content

数组

蜗牛排序

js
Array.prototype.snail = function (rowsCount, colsCount) {
  const { length } = this;
  if (rowsCount * colsCount !== length) {
    return [];
  }
  const res = new Array(rowsCount).fill(0).map(() => new Array(colsCount));
  let k = 0;
  for (let j = 0; j < colsCount; ++j) {
    if (j % 2 === 0) {
      for (let i = 0; i < rowsCount; ++i) {
        res[i][j] = this[k++];
      }
    } else {
      for (let i = rowsCount - 1; i >= 0; --i) {
        res[i][j] = this[k++];
      }
    }
  }
  return res;
};

扁平化嵌套数组

js
function flat(arr, n) {
  if (n <= 0) {
    return arr;
  }
  const res = [];
  for (const el of arr) {
    if (Array.isArray(el)) {
      res.push(...flat(el, n - 1));
    } else {
      res.push(el);
    }
  }
  return res;
}

分组

js
Array.prototype.groupBy = function (fn) {
  const res = {};
  for (const el of this) {
    const key = fn(el);
    if (!res[key]) {
      res[key] = [];
    }
    res[key].push(el);
  }
  return res;
};

嵌套数组生成器

js
function* inorderTraversal(arr) {
  for (const el of arr) {
    if (Array.isArray(el)) {
      yield* inorderTraversal(el);
    } else {
      yield el;
    }
  }
}

根据 ID 合并两个数组

js
function join(arr1, arr2) {
  const map = new Map();
  for (const arr of [arr1, arr2]) {
    for (const { id, ...rest } of arr) {
      const obj = map.get(id) ?? {};
      map.set(id, { ...obj, ...rest });
    }
  }
  return Array.from(map)
    .map(([id, obj]) => ({ id, ...obj }))
    .sort((a, b) => a.id - b.id);
}

数组原型对象的最后一个元素

js
Array.prototype.last = function () {
  if (!this.length) {
    return -1;
  }
  return this[this.length - 1];
};

数组归约运算

js
function reduce(nums, fn, init) {
  let res = init;
  for (const num of nums) {
    res = fn(res, num);
  }
  return res;
}

过滤数组中的元素

js
function filter(arr, fn) {
  const res = [];
  for (let i = 0; i < arr.length; ++i) {
    if (fn(arr[i], i)) {
      res.push(arr[i]);
    }
  }
  return res;
}

转换数组中的每个元素

js
function map(arr, fn) {
  const { length } = arr;
  const res = new Array(length);
  for (let i = 0; i < arr.length; ++i) {
    res[i] = fn(arr[i], i);
  }
  return res;
}

分块数组

js
function chunk(arr, size) {
  const { length } = arr;
  const chunkCount = Math.ceil(length / size);
  const res = new Array(chunkCount).fill(0).map(() => []);
  for (let i = 0; i < length; ++i) {
    res[Math.floor(i / size)].push(arr[i]);
  }
  return res;
}

包装数组

js
class ArrayWrapper {
  nums = [];

  constructor(nums) {
    this.nums = nums;
  }

  valueOf() {
    return this.nums.reduce((sum, num) => sum + num, 0);
  }

  toString() {
    return `[${this.nums.join(',')}]`;
  }
}

排序方式

js
function sortBy(arr, fn) {
  return arr.sort((a, b) => fn(a) - fn(b));
}

数组的上界

js
Array.prototype.upperBound = function (target) {
  const { length } = this;
  let lo = 0;
  let hi = length - 1;
  while (lo <= hi) {
    const mi = Math.floor((lo + hi) / 2);
    if (target < this[mi]) {
      hi = mi - 1;
    } else {
      lo = mi + 1;
    }
  }
  return lo > 0 && this[lo - 1] === target ? lo - 1 : -1;
};

数组原型的 forEach 方法

js
Array.prototype.forEach = function (callback, context) {
  const { length } = this;
  for (let i = 0; i < length; ++i) {
    callback.call(context, this[i], i, this);
  }
};