Group Objects By Key

You have 200 rows and need one email (or one Drive folder, or one export) per client. Nested loops and “remember the last name” logic get messy. groupObjectsByKey(rows, keyOrFn) turns an array of row objects into a plain map of key → [rows…] so the rest of the job is a simple for…in (or Object.keys).

When to use

  • Per-client / per-region digests and emails
  • Filing exports into one Drive folder per account
  • Splitting a big import into batches keyed by type or date

How to use this snippet

/** * Group an array of row objects by a field name or a key function. * Returns a plain object: { [key]: Object[] }. Blank/null keys become ''. * * @param {Object[]} rows * @param {string|function(Object):*} keyOrFn e.g. 'Client' or function(r){ return r.Region + '|' + r.Client; } * @return {Object.<string, Object[]>} */ function groupObjectsByKey(rows, keyOrFn) { var out = {}; if (!rows || !rows.length) return out; var getKey = typeof keyOrFn === 'function' ? keyOrFn : function (row) { return row[keyOrFn]; }; rows.forEach(function (row) { var key = getKey(row); // Keep blank keys in one bucket instead of inventing "undefined" if (key == null) key = ''; key = String(key); if (!out[key]) out[key] = []; out[key].push(row); }); return out; }

Example

function emailDigestPerClient() { var rows = readSheetData_(); // [{ Client, Email, Amount }, ...] var byClient = groupObjectsByKey(rows, 'Client'); Object.keys(byClient).forEach(function (client) { var group = byClient[client]; var to = group[0].Email; var body = group.map(function (r) { return r.Amount + ' — ' + (r.Note || ''); }).join('\n'); GmailApp.sendEmail(to, 'Digest for ' + client, body); }); } // Compound key: region + client var byRegionClient = groupObjectsByKey(rows, function (r) { return String(r.Region || '') + '|' + String(r.Client || ''); });

Tips:

  • Keys are always strings (String(key)). A number 42 and the string "42" land in the same bucket — usually what you want from a sheet.
  • Blank / missing keys go under ''. Filter them out before grouping if “no client” rows should be skipped, not emailed.
  • Order inside each group matches the input order. Sort the input first if you care.
  • This is a building block — pair it with filing, emails, or PDF export rather than reinventing the map each time.

Tip: NitroGAS Co-Pilot can wire groupObjectsByKey into an existing “email everyone” loop if you paste the function and say you want one email per Client.

Happy Coding!

NitroGAS Chrome Extension

Want this snippet handy inside the Apps Script editor? NitroGAS gives you free themes and snippets — plus optional Co-Pilot when you want a boost (1-week, 1-month, or yearly passes — no subscription). Happy Coding!

Get the Extension