信息发布→ 登录 注册 退出

J*aScript:从对象数组中提取具有唯一键值对的元素

发布时间:2025-12-04

点击量:

JavaScript:从对象数组中提取具有唯一键值对的元素

本教程详细介绍了如何在j*ascript中处理一个对象数组,从每个对象中移除那些在数组中先前对象中已经出现过的重复键值对。通过构建一个高效的“已见”映射表,我们将逐步指导您实现一个函数,该函数能够生成一个仅包含在各自对象中首次出现的唯一键值对的新对象数组,从而确保数据去重并保持原始结构。

理解问题与目标

在处理复杂的数据结构时,我们经常会遇到需要去重的情况。本教程关注的是一个特定的去重场景:给定一个包含多个对象的数组,我们希望创建一个新的数组,其中每个对象只保留那些在整个处理过程中首次出现的键值对。这意味着,如果一个 key: value 对已经在数组中的某个先前对象中出现过,那么它在当前对象中就应该被移除。

让我们通过一个示例来具体说明:

原始输入数组:

const arr1 = [
  {
    "Param1": "20",
    "Param2": "8",
    "Param3": "11",
    "Param4": "4",
    "Param5": "18",
    "Param6": "20",
    "Param7": "8"
  },
  {
    "Param6": "21",
    "Param7": "8",
    "Param8": "11",
    "Param9": "4",
    "Param10": "18"
  },
  {
    "Param1": "20",
    "Param2": "8",
    "Param3": "10"
  }
];

期望输出数组:

[
  {
    "Param1": "20",
    "Param2": "8",
    "Param3": "11",
    "Param4": "4",
    "Param5": "18",
    "Param6": "20",
    "Param7": "8"
  },
  {
    "Param6": "21", // Param6: "20" 已在第一个对象中出现,但 Param6: "21" 是新的
    "Param8": "11",
    "Param9": "4",
    "Param10": "18"
  },
  {
    "Param3": "10" // Param1: "20" 和 Param2: "8" 已在第一个对象中出现
  }
]

可以看到,在第二个对象中,"Param7": "8" 被移除了,因为它在第一个对象中已经出现过。同样,在第三个对象中,"Param1": "20" 和 "Param2": "8" 被移除,而 "Param3": "10" 被保留,因为它与第一个对象中的 "Param3": "11" 键相同但值不同,且 "Param3": "10" 之前未出现过。

核心算法思路

要实现上述去重逻辑,我们需要一个机制来“记住”所有已经处理过的键值对。最有效的方法是使用一个“已见”映射表(seen map)。这个映射表将存储每个键以及该键所对应的值是否已被发现过的信息。

算法步骤如下:

Tunee AI Tunee AI

新一代AI音乐智能体

Tunee AI 1104 查看详情 Tunee AI
  1. 初始化 seen 映射表: 创建一个空的 seen 对象(或 Map),其结构为 Record>,即 seen[key][value] = true 表示该键值对已被发现。
  2. 初始化 result 数组: 创建一个空的数组来存放处理后的新对象。
  3. 遍历输入数组: 逐个处理 arr1 中的每个对象。
  4. 处理当前对象: 对于每个对象:
    • 创建一个新的空对象 currentUniqueObject。
    • 遍历当前对象中的所有键值对。
    • 对于每个键 key 和值 value:
      • 首先,检查 seen[key] 是否已存在。如果不存在,则初始化 seen[key] 为一个空对象 {}。
      • 接着,检查 seen[key][value] 是否为 true。
        • 如果为 true,表示这个 key: value 对之前已经出现过,因此我们忽略它。
        • 如果为 false 或 undefined,表示这个 key: value 对是首次出现。
          • 将其添加到 currentUniqueObject 中。
          • 将 seen[key][value] 设置为 true,标记为已见。
  5. 添加结果: 将 currentUniqueObject 添加到 result 数组中。
  6. 返回 result: 遍历完成后,返回 result 数组。

J*aScript 实现

我们可以利用 Array.prototype.reduce 方法来优雅地实现这个算法,它允许我们迭代数组并累积一个单一的结果(在这里是 seen 映射表和 result 数组的组合)。

/**
 * 从对象数组中移除在先前对象中已出现过的重复键值对。
 *
 * @param arr 输入的对象数组,每个对象包含字符串键和字符串值。
 * @returns 包含唯一键值对的新对象数组。
 */
const removeDuplicates = (arr: Record<string, string>[]): Record<string, string>[] => {
    // 使用 reduce 方法来累积 'seen' 映射和 'result' 数组
    return arr.reduce<{
        seen: Record<string, Record<string, boolean>>; // 存储已见键值对的映射
        result: Record<string, string>[];              // 存储处理后的结果数组
    }>(
        (accumulator, currentItem) => {
            // 对于当前对象,筛选出唯一的键值对
            const uniqueItem = Object.fromEntries(
                Object.entries(currentItem).filter(([key, value]) => {
                    // 确保 seen[key] 存在,如果不存在则初始化为 {}
                    accumulator.seen[key] = accumulator.seen[key] ?? {};

                    // 检查当前键值对是否已在 'seen' 映射中
                    if (accumulator.seen[key][value]) {
                        // 如果已见,则过滤掉(返回 false)
                        return false;
                    }

                    // 如果未见,则标记为已见(设置为 true)
                    accumulator.seen[key][value] = true;
                    // 并保留该键值对(返回 true)
                    return true;
                }),
            );
            // 将处理后的唯一对象添加到结果数组中
            accumulator.result.push(uniqueItem);
            return accumulator;
        },
        // reduce 的初始值:一个包含空 'seen' 映射和空 'result' 数组的对象
        { seen: {}, result: [] },
    ).result; // 最后返回累加器中的 'result' 数组
};

示例用法

现在,让我们将 removeDuplicates 函数应用于我们之前的示例数据:

const arr1 = [
  {
    "Param1": "20",
    "Param2": "8",
    "Param3": "11",
    "Param4": "4",
    "Param5": "18",
    "Param6": "20",
    "Param7": "8"
  },
  {
    "Param6": "21",
    "Param7": "8",
    "Param8": "11",
    "Param9": "4",
    "Param10": "18"
  },
  {
    "Param1": "20",
    "Param2": "8",
    "Param3": "10"
  }
];

const uniqueArray = removeDuplicates(arr1);
console.log(JSON.stringify(uniqueArray, null, 2));

输出结果:

[
  {
    "Param1": "20",
    "Param2": "8",
    "Param3": "11",
    "Param4": "4",
    "Param5": "18",
    "Param6": "20",
    "Param7": "8"
  },
  {
    "Param6": "21",
    "Param8": "11",
    "Param9": "4",
    "Param10": "18"
  },
  {
    "Param3": "10"
  }
]

这个输出与我们预期的结果完全一致,成功地移除了所有重复的键值对。

注意事项与总结

  1. 数据类型限制: 本实现假设对象的值是字符串。如果值可以是其他类型(如数字、布尔值、对象等),seen 映射的键(value 部分)可能需要进行调整,例如使用 JSON.stringify 来确保唯一性,但这会带来性能开销。对于原始类型(字符串、数字等),当前方法是高效的。
  2. 时间复杂度: 算法的时间复杂度大致为 O(N * K),其中 N 是输入数组中对象的数量,K 是每个对象中键值对的平均数量。这是因为我们需要遍历每个对象,并对每个对象的每个键值对进行查找和插入操作。
  3. 空间复杂度: 空间复杂度主要取决于 seen 映射表的大小,它将存储所有不重复的键值对。在最坏情况下(所有键值对都不同),空间复杂度为 O(N * K)。
  4. 不可变性: removeDuplicates 函数返回一个全新的数组和全新的对象,不会修改原始输入 arr1,这符合函数式编程的良好实践。

通过本教程,您已经学会了如何使用 Array.prototype.reduce 和一个自定义的“已见”映射表来高效地从对象数组中提取并保留那些在处理过程中首次出现的键值对。这种模式在处理需要基于历史状态进行数据过滤的场景中非常有用。

以上就是J*aScript:从对象数组中提取具有唯一键值对的元素的详细内容,更多请关注其它相关文章!


相关文章: PDF文件体积过大处理_PDF压缩技巧详解  内存疯狂猛猛涨价:主板销量直接腰斩!  ArrayList与LinkedList核心操作的Big-O复杂度分析  极速漫画官方主页网址 极速漫画漫画在线浏览官网链接  Python模块化编程:有效管理依赖与避免循环引用  纯CSS与HTML网格布局的HTML精简策略:SVG与JS方案解析  sublime怎么预览Markdown渲染效果_Markdown Preview插件 for sublime教程  京东单号查询入口_京东快递订单追踪入口  Google翻译怎么语音输入_Google翻译语音输入功能使用与设置方法  J*aScript设计模式实践_j*ascript代码优化  蛙漫画网页版全站入口 蛙漫热门作品免费浏览  NVIDIA股价11月重挫12%:下月有望好转 但难回5万亿美元巅峰  c++中的std::launder有什么实际用途_c++对象生命周期与指针优化  Flexbox布局实践:实现粘性导航栏与底部固定页脚  Win10怎么设置静态IP地址 Win10手动配置IP地址步骤【指南】  多闪网页版在线观看免费入口_多闪官网访问入口  Tailwind CSS line-clamp 布局问题解析与修复指南  J*aScript实现动态背景色下的文本与按钮颜色自适应调整  css元素hover动画延迟生效怎么办_使用animation-delay调整触发时间  J*aScript 字符串标签转换:使用正则表达式高效替换  漫蛙漫画登录站点 漫蛙2正版漫画快速访问  蛙漫官方正版入口 蛙漫网页在线全集免费观看  新手怎么开始学化妆 零基础化妆入门教程  蛙漫漫画免费阅读入口_蛙漫官方正版无广告纯净版  在J*a中如何使用BigDecimal进行高精度计算_BigDecimal类应用指南  Python getattr() 异常处理深度解析:避免程序意外退出  深入理解J*a链表中的IPosition接口与使用  Lar*el用户头像管理:实现图片缩放、存储与旧文件安全删除的最佳实践  怎么搭建一个php网站源码_搭php网站源码搭建教程  word中如何让数字纵向排列_Word数字纵向排列方法  css链接悬停下划线样式如何自定义_使用::after结合content和transition  PHP表单隐藏域数据传递:常见问题与最佳实践  黑鲨3Pro怎样在相册开漫画风滤镜_iPhone黑鲨3Pro相册开漫画风滤镜【趣味滤镜】  使用Python高效删除Word宏并转换DOCM为DOCX格式  将HTML Canvas内容转换为可上传的图像文件(File对象)  12306选座如何查看座位示意图_12306座位示意图解读与使用  神经网络二分类模型训练异常:高损失与完美验证准确率的排查与修正  J*a里如何使用forEach遍历Map_Map遍历方法说明  微信语音通话掉线如何解决 微信语音通话稳定优化方法  ArchiveofOurOwn小说阅读-ArchiveofOurOwn同人作品访问链接  msn官网入口地址手机版 msn官方网站手机最新链接  谷歌google账号注册详细步骤 谷歌账号注册官方教程  在React函数组件中利用原生HTML5进行邮箱地址验证  HTML空白字符处理机制:渲染、DOM与编码实践  fishbowl官网免费版 fishbowl养鱼网站入口  Lar*el Eloquent:高效统计带条件关联模型的数量  PHP教程:高效从URL路径中提取倒数第二个片段  c++20的std::jthread是什么_c++可中断线程与RAII式管理  ACG动漫手机版官网入口 手机ACG动漫APP在线观看正版  《明末:渊虚之羽》设计师谈设计角色:那会刚毕业 充满激情 

在线客服
服务热线

服务热线

4008988990

微信咨询
二维码
返回顶部
×二维码

截屏,微信识别二维码

打开微信

微信号已复制,请打开微信添加咨询详情!