LeetCode 题解:2631. 分组

297 阅读2分钟

原题链接

leetcode.cn/problems/gr…

题目解析

题目要求我们为数组原型添加一个名为groupBy的方法,该方法接受一个函数fn作为参数,并返回一个对象。这个对象的键是fn函数的返回值,值是与该键相关的数组元素的数组。

解题思路

解法1:使用reduce方法

/**
 * 使用 reduce 方法实现 groupBy
 * @param {Function} fn - 用于生成分组键的函数
 * @return {Object} - 分组后的对象
 */
Array.prototype.groupBy = function(fn) {
  return this.reduce((res, curr) => {
    // 使用 fn 函数计算当前元素的键
    const key = fn(curr);
    // 如果结果对象中还没有这个键,就创建一个新数组
    // 然后将当前元素添加到这个数组中
    (res[key] ??= []).push(curr);
    return res;
  }, {});
};

可以进一步简写成:

/**
 * @param {Function} fn
 * @return {Array}
 */
Array.prototype.groupBy = function(fn) {
  return this.reduce((res, curr) => ((res[fn(curr)] ??= []).push(curr), res), {})
};

优点:

  1. 简洁性reduce是JavaScript数组的一个高阶函数,它可以简洁地对数组进行迭代并返回一个累积结果。
  2. 函数式编程:这种方法采用了函数式编程的风格,使得代码更加紧凑。

缺点:

  1. 可读性:对于不熟悉reduce方法的开发者来说,可能需要花一些时间来理解它的工作原理。

解法2:使用for...of循环

/**
 * 使用 for...of 循环实现 groupBy
 * @param {Function} fn - 用于生成分组键的函数
 * @return {Object} - 分组后的对象
 */
Array.prototype.groupBy = function(fn) {
  let obj = {};

  for (const item of this) {
    const key = fn(item);
    // 如果结果对象中还没有这个键,就创建一个新数组
    if (!obj[key]) {
      obj[key] = [item];
    } else {
      // 否则,将当前元素添加到与该键相关的数组中
      obj[key].push(item);
    }
  }

  return obj;
};

优点:

  1. 可读性:这种解法的可读性很好,它明确地描述了如何构建结果对象,并且没有使用任何高阶函数或复杂的语法。
  2. 直观性:这种解法使用了传统的循环结构,对于大多数开发者来说都很熟悉。

缺点:

  1. 代码长度:与reduce方法相比,这种方法的代码稍微长一些。

总结

两种解法在效率上都是相似的,但在可读性和简洁性上有所不同。如果你更喜欢函数式编程的风格,并且希望代码尽可能地简洁,那么解法1可能更适合你。如果你希望代码更加直观和易于理解,那么解法2可能更适合你。总的来说,选择哪种解法取决于你的个人喜好和项目的需求。在实际开发中,考虑到代码的可读性和维护性通常是很重要的。