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

TypeScript 中含动态元素的对象数组如何按键提取全部唯一值

TypeScript 动态无Schema对象数组的键值聚合去重实现

需求与场景

  • 输入为无固定Schema约束的对象数组,数组元素的顶层键(如Value1/Value2)、键对应的字符串值(如name/age)均为动态生成,无固定类型约束
  • 目标输出为聚合对象:属性为原数组元素的顶层键,属性值为对应键下所有出现过的字符串值去重后的数组
  • 此前使用array.reduce()实现未得到预期效果,以下为适配动态键场景的可行方案

Reduce实现常见失败原因

  • 未显式指定reduce的初始值:默认取数组第一个元素作为初始值,导致类型不匹配、逻辑错乱
  • 硬编码访问固定键:未遍历当前对象的所有动态键,导致运行时新增的动态键被遗漏
  • 未做去重直接push值:结果中残留同键的重复值

基础实现(中小数据量适用)

类型定义

// 原始输入元素类型:任意字符串键对应字符串值
type DynamicObject = Record<string, string>;
// 聚合结果类型
type AggregatedResult = Record<string, string[]>;

完整实现代码

// 示例输入数组(模拟动态生成的无Schema结构)
const inputArray: DynamicObject[] = [
  { Value1: "name", Value2: "surname" },
  { Value1: "age", Value3: "hoursWorked" },
  { Value2: "surname", Value3: "hoursWorked" },
  { Value1: "name" },
];

const aggregatedResult = inputArray.reduce<AggregatedResult>((acc, currObj) => {
  // 遍历当前对象的所有动态顶层键
  Object.keys(currObj).forEach((key) => {
    const currentValue = currObj[key];
    // 首次出现该键时初始化对应数组
    if (!acc[key]) acc[key] = [];
    // 去重判断:仅当前值不存在时才插入
    if (!acc[key].includes(currentValue)) acc[key].push(currentValue);
  });
  return acc;
}, {}); // 必须显式传入空对象作为初始值

输出示例

{
  Value1: ["name", "age"],
  Value2: ["surname"],
  Value3: ["hoursWorked"]
}

性能优化实现(大数据量适用)

当数组长度较大、单键下唯一值较多时,使用Set的自动去重特性可降低查询的时间复杂度:

// 中间层用Map存储键和对应Set,避免O(n)的includes查询
const tempMap = inputArray.reduce<Map<string, Set<string>>>((acc, currObj) => {
  Object.entries(currObj).forEach(([key, value]) => {
    if (!acc.has(key)) acc.set(key, new Set());
    // Set自动去重,无需手动判断重复
    acc.get(key)!.add(value);
  });
  return acc;
}, new Map());

// 转换为要求的最终对象格式
const finalResult: AggregatedResult = Object.fromEntries(
  Array.from(tempMap.entries()).map(([key, valueSet]) => [key, Array.from(valueSet)])
);

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.25 18:54:02