← Back to Blog
Code Snippets July 9, 2026

GroupBy Utility — Group Any Array by Key, Nested Path, or Function (JS)

🌐 Code Snippet — July 9, 2026

GroupBy Utility — Group Any Array by Key, Nested Path, or Function (JS)

Stop rewriting arr.reduce((acc, item) => { ... }, {}) in every file. This ~35-line utility handles string keys, dot-notation paths ("address.city"), custom functions, null handling, and Map mode.

function getNestedValue(obj, path) {
  return path.split('.').reduce((cur, key) => {
    if (cur === null || cur === undefined) return undefined;
    return cur[key];
  }, obj);
}

function groupBy(array, groupingKey, options = {}) {
  const { asMap = false } = options;
  const collector = asMap ? new Map() : {};

  const resolveGroup = (item) => {
    if (typeof groupingKey === 'function') return groupingKey(item);
    if (typeof groupingKey === 'string') {
      const v = getNestedValue(item, groupingKey);
      return (v === null || v === undefined) ? '__null__' : String(v);
    }
    throw new TypeError('groupBy key must be a string or function');
  };

  for (const item of array) {
    const group = resolveGroup(item);
    if (asMap) {
      if (!collector.has(group)) collector.set(group, []);
      collector.get(group).push(item);
    } else {
      if (!collector[group]) collector[group] = [];
      collector[group].push(item);
    }
  }
  return collector;
}

// Bonus: countBy in one line
const countBy = (arr, key) =>
  Object.fromEntries(
    Object.entries(groupBy(arr, key)).map(([k, v]) => [k, v.length])
  );


Usage:
groupBy(users, 'department')              // Simple key
groupBy(orders, 'shipping.address.country')  // Dot-notation
groupBy(items, i => i.price > 100 ? 'premium' : 'standard')  // Function
groupBy(items, 'category', { asMap: true })   // Returns Map
countBy(orders, 'status')  // → { pending: 3, shipped: 2, ... }


💡 Array.prototype.groupBy() is coming to native JS in 2026, but this works today in every environment with bonus features.