Clean Markup

Native Collection Categorization with Object groupBy and Map groupBy

Native Collection Categorization with Object groupBy and Map groupBy

Grouping elements of an array by a computed category or property has long been one of JavaScript's most common yet syntactically cumbersome operations. For years, frontend and backend engineers routinely imported large utility libraries such as Lodash or Ramda solely for grouping helpers, or crafted verbose Array.prototype.reduce() expressions that required manually initializing bucket arrays, checking for key existence, and juggling accumulator objects. This pattern frequently introduced unnecessary boilerplate and subtle mutation bugs into production codebases.

Standardized in ECMAScript 2024 and supported across modern browsers and Node.js environments, Object.groupBy() and Map.groupBy() bring native, high-performance categorization to all JavaScript iterables. While Object.groupBy() produces a null-prototype object that converts keys to strings or symbols, Map.groupBy() preserves arbitrary object references and primitive types as dictionary keys. This architectural distinction guarantees protection against object prototype pollution while empowering developers to structure complex data pipelines cleanly without external dependencies.

Example

const inventory = [
  { sku: 'A100', name: 'Mechanical Keyboard', category: 'electronics', stock: 14 },
  { sku: 'B200', name: 'Ergonomic Chair', category: 'furniture', stock: 3 },
  { sku: 'A101', name: 'USB-C Cable', category: 'electronics', stock: 52 },
  { sku: 'B201', name: 'Standing Desk', category: 'furniture', stock: 0 }
];

// Native Object.groupBy creates a clean, null-prototype object
const byCategory = Object.groupBy(inventory, (item) => item.category);

console.log(Object.getPrototypeOf(byCategory)); // null (safe from prototype pollution)
console.log(byCategory.electronics.length); // 2

Implementation

/**
 * Real-world e-commerce inventory and order categorization
 * Demonstrating both Object.groupBy and Map.groupBy workflows
 */

// 1. Grouping inventory items with Object.groupBy
const products = [
  { id: 'p1', name: 'Studio Monitor Headphones', price: 149.99, quantity: 18 },
  { id: 'p2', name: '4K Display Monitor', price: 399.00, quantity: 4 },
  { id: 'p3', name: 'Desk Cable Sleeve', price: 12.50, quantity: 0 },
  { id: 'p4', name: 'Vertical Mouse', price: 79.95, quantity: 22 },
  { id: 'p5', name: 'Microphone Arm', price: 45.00, quantity: 2 }
];

// Categorize inventory by availability status
const inventoryByStockStatus = Object.groupBy(products, (product) => {
  if (product.quantity === 0) return 'outOfStock';
  if (product.quantity <= 5) return 'lowStock';
  return 'inStock';
});

console.log('Out of stock:', inventoryByStockStatus.outOfStock?.map(p => p.name));
console.log('Low stock alerts:', inventoryByStockStatus.lowStock?.map(p => p.name));

// 2. Grouping customer orders with Map.groupBy using complex object references as keys
const priorityTiers = {
  vip: { label: 'VIP Priority', slaHours: 2, freeShipping: true },
  standard: { label: 'Standard Customer', slaHours: 24, freeShipping: false }
};

const orders = [
  { orderId: 'ORD-501', customerTier: priorityTiers.vip, total: 320.00 },
  { orderId: 'ORD-502', customerTier: priorityTiers.standard, total: 45.50 },
  { orderId: 'ORD-503', customerTier: priorityTiers.vip, total: 1200.00 },
  { orderId: 'ORD-504', customerTier: priorityTiers.standard, total: 89.20 }
];

// Map.groupBy uses the actual tier object reference without string coercion
const ordersByTier = Map.groupBy(orders, (order) => order.customerTier);

for (const [tier, orderList] of ordersByTier.entries()) {
  const aggregateValue = orderList.reduce((sum, o) => sum + o.total, 0);
  console.log(`[${tier.label}] Fulfillment SLA: ${tier.slaHours}h`);
  console.log(`Total orders: ${orderList.length}, Revenue: $${aggregateValue.toFixed(2)}`);
}

Main Point: Native Object.groupBy and Map.groupBy eliminate reduce boilerplate and external libraries, delivering fast and safe categorization with support for both string keys and complex object references.

Credits

Photo by Scott Webb on Unsplash

← Home