You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

按n个键或嵌套键高效分组对象数组的最优方法

Efficiently Grouping Object Arrays by Entire Objects, Specific Keys, or Nested Keys

Great question! Let's walk through how to tackle grouping object arrays into the structure you need—whether you're grouping by the full object (like your example), a set of specific keys, or even nested keys. We'll focus on efficient, reusable implementations that work for most real-world scenarios.

1. Grouping by Entire Objects (Your Example Scenario)

First, let's solve your exact use case: grouping duplicate objects into sub-arrays. The core challenge here is that JavaScript objects are reference types, so you can't use them directly as keys in a map or object. Instead, we need to create a unique, consistent identifier for each object's content.

Implementation

We’ll use Array.reduce() with a Map (more efficient than plain objects for grouping, especially with large datasets) to track groups, then convert the Map’s values to your desired array structure:

const data = [
  {a: 1, b: 2, c:3},
  {d: 4, e: 5, f: 6},
  {a: 1, b: 2, c:3},
  {g: 7, h: 8, i: 9},
  {d: 4, e: 5, f: 6},
  {g: 7, h: 8, i: 9},
];

// Group by entire object content
const groupedByObject = Array.from(
  data.reduce((map, obj) => {
    // Create a consistent key by sorting object entries before stringifying
    const sortedEntries = Object.entries(obj).sort();
    const key = JSON.stringify(Object.fromEntries(sortedEntries));
    // Add the object to its group (or create a new group if it doesn't exist)
    map.set(key, [...(map.get(key) || []), obj]);
    return map;
  }, new Map())
);

console.log(groupedByObject);
// Output matches your desired grouped structure!

Key Notes

  • Sorting object entries before stringifying ensures that objects with the same key-value pairs in different orders (e.g., {a:1, b:2} vs {b:2, a:1}) generate the same group key.
  • Map is preferred over plain objects because it handles non-string keys better and has consistent O(1) time complexity for get/set operations.

2. Grouping by a Set of Specific Keys (n Keys)

If you don’t want to group by the entire object, but instead by a subset of keys (e.g., group by a and b), we can build a reusable function that accepts your target keys as a parameter.

Implementation

/**
 * Groups an array of objects by a set of specified keys
 * @param {Array} arr - The array to group
 * @param {Array} keys - The keys to use for grouping
 * @returns {Array} Array of grouped sub-arrays
 */
function groupByKeys(arr, keys) {
  return Array.from(
    arr.reduce((map, obj) => {
      // Create a key from the specified keys' values (sorted for consistency)
      const sortedKeys = keys.sort();
      const keyValues = sortedKeys.map(key => obj[key]);
      const groupKey = JSON.stringify(keyValues);
      
      map.set(groupKey, [...(map.get(groupKey) || []), obj]);
      return map;
    }, new Map())
  );
}

// Example usage: group by keys 'a' and 'b'
const sampleData = [
  {a:1, b:2, c:3},
  {a:1, b:2, d:4},
  {a:2, b:3, e:5},
  {a:1, b:2, f:6},
];

const groupedByAB = groupByKeys(sampleData, ['a', 'b']);
console.log(groupedByAB);
// Output: [[{a:1,b:2,c:3}, {a:1,b:2,d:4}, {a:1,b:2,f:6}], [{a:2,b:3,e:5}]]

Key Notes

  • Sorting the input keys ensures that passing the same set of keys in any order (e.g., ['a','b'] vs ['b','a']) generates the same group key.
  • This function works for any number of keys—1, 2, or n—making it flexible for different use cases.

3. Grouping by Nested Keys

For nested keys (e.g., user.address.city), we first need a helper function to safely extract nested values from objects, then use that value as our group key.

Implementation

First, the helper function to get nested values:

/**
 * Safely gets a nested value from an object
 * @param {Object} obj - The target object
 * @param {String} path - Dot-separated path to the nested value (e.g., 'user.address.city')
 * @returns {*} The nested value, or undefined if the path doesn't exist
 */
function getNestedValue(obj, path) {
  return path.split('.').reduce((current, key) => {
    return current && current[key] !== undefined ? current[key] : undefined;
  }, obj);
}

Then, the grouping function for nested keys:

/**
 * Groups an array of objects by a nested key path
 * @param {Array} arr - The array to group
 * @param {String} nestedPath - Dot-separated path to the nested key
 * @returns {Array} Array of grouped sub-arrays
 */
function groupByNestedKey(arr, nestedPath) {
  return Array.from(
    arr.reduce((map, obj) => {
      const key = getNestedValue(obj, nestedPath);
      // Handle cases where the nested path doesn't exist (group under a fallback key)
      const groupKey = key !== undefined ? JSON.stringify(key) : 'undefined-group';
      
      map.set(groupKey, [...(map.get(groupKey) || []), obj]);
      return map;
    }, new Map())
  );
}

// Example usage: group by 'user.address.city'
const nestedData = [
  {user: {name: 'Alice', address: {city: 'New York'}}},
  {user: {name: 'Bob', address: {city: 'London'}}},
  {user: {name: 'Charlie', address: {city: 'New York'}}},
  {user: {name: 'Dave'}}, // No address key
];

const groupedByCity = groupByNestedKey(nestedData, 'user.address.city');
console.log(groupedByCity);
// Output: [[{user: {...city: 'New York'}}, {user: {...city: 'New York'}}], [{user: {...city: 'London'}}], [{user: {name: 'Dave'}}]]

Efficiency Considerations

  • Time Complexity: All implementations run in O(n * k) time, where n is the number of objects in the array, and k is the time to generate the group key (stringifying keys/objects or traversing nested paths). This is optimal for most real-world scenarios.
  • Map vs. Plain Objects: Map is more reliable for grouping because it doesn’t coerce keys to strings (though we use stringified keys here for consistency) and avoids conflicts with built-in object properties (like toString).
  • Stringify Alternatives: If you need even better performance, you can create custom hash strings instead of JSON.stringify (e.g., concatenating key-value pairs with a unique separator). However, JSON.stringify is the most straightforward and consistent method for most cases.

内容的提问来源于stack exchange,提问作者Pommesloch

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.08 15:03:10