讲师中心 微信公众号

工具推荐

视频效率加速
立刻MV
立刻MV

低成本歌曲 MV、视频生成

Seko
Seko

AI短剧一键生成成片

Laper
Laper

剧本策划到成片协作

updream

一键生成高质量推广成片

JavaScript/Vuex:高效过滤对象数组,确保特定键值唯一性

落杰酱_6681

落杰酱_6681

发布时间:2025-07-22 20:22:11

|

250人浏览过

|

来源于php中文网

原创

JavaScript/Vuex:高效过滤对象数组,确保特定键值唯一性

本文旨在探讨在JavaScript环境中,尤其是在Vuex应用中,如何高效地从一个对象数组中筛选出具有特定键值唯一性的元素。我们将详细分析常见的过滤方法,包括reduce、Map和Set的运用,并提供具体的代码示例,帮助开发者正确实现数据去重,避免常见错误,并确保代码的健壮性和性能。

在前端开发中,我们经常会遇到需要处理数组数据,并从中提取出符合特定条件(例如某个属性值唯一)的元素。当数据来源于vuex状态管理时,这种需求尤为常见。本教程将以一个具体的场景为例,演示如何从包含重复trip_class属性的对象数组中,筛选出trip_class值唯一的对象。

问题分析与常见误区

假设我们有一个flights数组,其结构如下:

[
    {name: 'john', trip_class: 0, lastname: 'lastname'},
    {name: 'Don', trip_class: 1, lastname: 'lastname'},
    {name: 'Joshua', trip_class: 1, lastname: 'lastname'}, // trip_class: 1 重复
    {name: 'Mary', trip_class: 2, lastname: 'lastname'}
]

我们期望得到的结果是trip_class唯一的数组:

[
    {name: 'john', trip_class: 0, lastname: 'lastname'},
    {name: 'Don', trip_class: 1, lastname: 'lastname'},
    {name: 'Mary', trip_class: 2, lastname: 'lastname'}
]

在尝试使用reduce方法进行去重时,一个常见的错误是find方法的条件判断不正确。例如,以下代码段中:

flightsClasses.reduce((acc, obj)=>{
  var exist = acc.find((flightClass) => obj.trip_class === flightClass ); // 错误:将 trip_class 与整个对象进行比较
  if(!exist){
    acc.push(obj);
  }
  return acc;
},[]);

acc.find((flightClass) => obj.trip_class === flightClass ) 这行代码的意图是检查累加器acc中是否已存在具有相同trip_class的对象。然而,flightClass是一个完整的对象,而obj.trip_class是一个数值。将一个数值与一个对象进行严格相等(===)比较,结果将始终为false,导致所有元素都被添加到结果数组中,无法实现去重。

立即学习“Java免费学习笔记(深入)”;

正确的解决方案

要正确地实现基于特定键值的去重,我们需要确保find方法比较的是对象的对应属性。

方案一:使用 Array.prototype.reduce()

reduce方法是一个强大的工具,可以用于将数组归约为单个值。在这里,我们可以用它来构建一个新的、去重后的数组。

// 假设 this.flights 是从 Vuex getter 获取的原始数组
computed: {
    flights() {
        return this.$store.getters.getFlights;
    },
    flightsClasses() {
        // 使用 reduce 方法进行去重
        const uniqueFlights = this.flights.reduce((accumulator, currentObject) => {
            // 检查累加器中是否已存在具有相同 trip_class 的对象
            const exists = accumulator.find(item => item.trip_class === currentObject.trip_class);

            // 如果不存在,则将当前对象添加到累加器中
            if (!exists) {
                accumulator.push(currentObject);
            }
            return accumulator;
        }, []); // 初始累加器为空数组

        return uniqueFlights;
    }
}

解释:

  1. reduce方法遍历this.flights数组中的每个currentObject。
  2. accumulator是累加器,它在每次迭代中都会传递下去,并最终成为去重后的数组。
  3. accumulator.find(item => item.trip_class === currentObject.trip_class):这是关键的修正。我们现在比较的是currentObject.trip_class(当前对象的trip_class值)与item.trip_class(累加器中已有对象的trip_class值)。如果找到匹配项,exists将为true,表示该trip_class已存在。
  4. 如果exists为false(即trip_class是新的),则将currentObject添加到accumulator中。

方案二:使用 Map 对象(推荐)

Map对象是ES6中引入的一种新的数据结构,它保存键值对,并且键可以是任何类型。使用Map进行去重通常更高效,因为它提供了O(1)的查找速度(平均情况下),而find方法在最坏情况下是O(n)。

Springboot Vue Builder
Springboot Vue Builder

从零开始编排 SpringBoot+Vue 全栈项目工作流,适用于新建全栈项目或完整脚手架请求,触发后依次调用 product‑spec‑builder(需求调研)等模块。

下载
computed: {
    flights() {
        return this.$store.getters.getFlights;
    },
    flightsClasses() {
        const uniqueMap = new Map();
        this.flights.forEach(item => {
            // 使用 trip_class 作为 Map 的键,将整个对象作为值
            // 如果键已存在,新的值会覆盖旧的值,从而达到去重目的(保留最后一个)
            // 如果希望保留第一个出现的,可以在 set 之前检查 uniqueMap.has(item.trip_class)
            if (!uniqueMap.has(item.trip_class)) { // 确保保留第一个出现的对象
                uniqueMap.set(item.trip_class, item);
            }
        });
        // 将 Map 的值转换为数组
        return Array.from(uniqueMap.values());
    }
}

解释:

  1. 我们创建一个新的Map实例。
  2. 遍历原始flights数组。
  3. 对于每个item,我们使用item.trip_class作为Map的键,并将整个item对象作为值存储起来。
  4. 由于Map的键是唯一的,如果遇到重复的trip_class,uniqueMap.set()操作会覆盖之前的值(如果if条件不加,则保留最后一个;加上if条件则保留第一个)。
  5. 最后,Array.from(uniqueMap.values())将Map中存储的所有值(即去重后的对象)转换为一个新的数组。

方案三:使用 Set 和 filter

虽然Set本身只能存储唯一的值,但它不能直接存储唯一的对象(因为对象是引用类型,即使内容相同,引用不同也被认为是不同的)。不过,我们可以结合Set来存储已见的trip_class值,然后用filter来构建新数组。

computed: {
    flights() {
        return this.$store.getters.getFlights;
    },
    flightsClasses() {
        const seenTripClasses = new Set();
        return this.flights.filter(item => {
            if (!seenTripClasses.has(item.trip_class)) {
                seenTripClasses.add(item.trip_class);
                return true; // 保留此元素
            }
            return false; // 过滤掉此元素
        });
    }
}

解释:

  1. 创建一个Set来存储所有已经处理过的trip_class值。
  2. 使用filter方法遍历flights数组。
  3. 对于每个item,检查其trip_class是否已存在于seenTripClasses中。
  4. 如果不存在,则将其添加到seenTripClasses中,并返回true(表示保留该元素)。
  5. 如果已存在,则返回false(表示过滤掉该元素)。

Vuex集成注意事项

在Vue组件的computed属性中使用上述逻辑是处理Vuex状态的推荐方式。computed属性具有缓存机制,只有当其依赖项(如this.$store.getters.getFlights)发生变化时,才会重新计算。这确保了性能优化,避免了不必要的重复计算。

  • Getter的使用: 确保你的Vuex store中有一个getter来暴露原始的flights数组,例如:

    // store/modules/flights.js
    const state = {
        allFlights: []
    };
    
    const getters = {
        getFlights: (state) => state.allFlights
    };
    
    const mutations = {
        setFlights: (state, flights) => {
            state.allFlights = flights;
        }
    };
    
    export default {
        state,
        getters,
        mutations
        // ... actions
    };
  • 数据不可变性: 上述所有方法都会返回一个新的数组,而不是修改原始数组。这符合Vue和Vuex的数据不可变性原则,有助于避免意外的副作用和更清晰的状态管理。

总结

从对象数组中根据特定键值去重是一个常见的编程任务。理解各种方法的优缺点并选择最适合的方案至关重要。

  • reduce方法 提供了灵活的累加逻辑,但内部的find操作在大型数组中可能效率较低。
  • Map对象 是处理这种去重场景的首选,因为它提供了接近O(1)的查找速度,在性能上表现优秀。
  • Set结合filter 也是一个可行的方案,其可读性良好,性能也优于纯reduce加find。

在Vuex应用中,将这些去重逻辑封装在computed属性中,可以充分利用Vue的响应式系统和缓存机制,确保数据处理的高效和准确。选择哪种方法取决于你的具体需求、数据量以及对代码可读性和性能的权衡。

热门AI工具

更多
豆包大模型

豆包大模型是一款由字节跳动推出的企业级大语言模型服务平台。

Seko
Seko Hot

一款AI视频创作工具,主要用于商汤科技推出的创编一体的AI短视频创作Agent,适合需要提升相关任务效率的用户。

墨刀AI
墨刀AI Hot

一款AI图像与设计工具,主要用于产品经理的专属智能体,适合需要提升相关任务效率的用户。

WorkBuddy

一款AI办公效率工具,主要用于腾讯云推出的AI原生桌面智能体工作台,适合需要提升相关任务效率的用户。

切问学术

切问学术是一款AI论文写作工具,复旦大学NLP团队推出的AI学术智能体。

DeepSeek

DeepSeek是一款面向对话、写作、编程和推理场景的AI大模型工具。

Lovart
Lovart Hot

一款面向视觉设计创作的AI设计平台,可通过智能体和画布工作流辅助制作海报、Logo、网页、PPT及其他视觉内容。

小橡皮AI

一款AI工具,主要用于小橡皮一键去AI味,将机器味重的内容改得更有活人感,防止因为 AI 内容被平台打上 AI 标签,以及限流,适合需要提升相关任务效率的用户。

PixTV
PixTV Hot

PixTV是一款面向AIGC内容创作的AI视频生成工具。

相关专题

更多
es6新特性
es6新特性

es6新特性有:1、块级作用域变量;2、箭头函数;3、模板字符串;4、解构赋值;5、默认参数;6、 扩展运算符;7、 类和继承;8、Promise。本专题为大家提供es6新特性的相关的文章、下载、课程内容,供大家免费下载体验。

305

2023.07.17

es6新特性有哪些
es6新特性有哪些

es6的新特性有:1、块级作用域;2、箭头函数;3、解构赋值;4、默认参数;5、扩展运算符;6、模板字符串;7、类和模块;8、迭代器和生成器;9、Promise对象;10、模块化导入和导出等等。本专题为大家提供es6新特性的相关的文章、下载、课程内容,供大家免费下载体验。

406

2023.08.04

JavaScript ES6新特性
JavaScript ES6新特性

ES6是JavaScript的根本性升级,引入let/const实现块级作用域、箭头函数解决this绑定问题、解构赋值与模板字符串简化数据处理、对象简写与模块化提升代码可读性与组织性。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

395

2025.12.24

treenode的用法
treenode的用法

​在计算机编程领域,TreeNode是一种常见的数据结构,通常用于构建树形结构。在不同的编程语言中,TreeNode可能有不同的实现方式和用法,通常用于表示树的节点信息。更多关于treenode相关问题详情请看本专题下面的文章。php中文网欢迎大家前来学习。

2941

2023.12.01

C++ 高效算法与数据结构
C++ 高效算法与数据结构

本专题讲解 C++ 中常用算法与数据结构的实现与优化,涵盖排序算法(快速排序、归并排序)、查找算法、图算法、动态规划、贪心算法等,并结合实际案例分析如何选择最优算法来提高程序效率。通过深入理解数据结构(链表、树、堆、哈希表等),帮助开发者提升 在复杂应用中的算法设计与性能优化能力。

416

2025.12.22

深入理解算法:高效算法与数据结构专题
深入理解算法:高效算法与数据结构专题

本专题专注于算法与数据结构的核心概念,适合想深入理解并提升编程能力的开发者。专题内容包括常见数据结构的实现与应用,如数组、链表、栈、队列、哈希表、树、图等;以及高效的排序算法、搜索算法、动态规划等经典算法。通过详细的讲解与复杂度分析,帮助开发者不仅能熟练运用这些基础知识,还能在实际编程中优化性能,提高代码的执行效率。本专题适合准备面试的开发者,也适合希望提高算法思维的编程爱好者。

437

2026.01.06

C++ 数据结构与算法实现教程合集
C++ 数据结构与算法实现教程合集

以 C++ 为实现语言,系统讲解核心数据结构与算法,涵盖链表(单链表/双链表/环检测)、栈与队列(单调栈/优先队列)、二叉树(遍历/BST/AVL/红黑树)、哈希表(开地址法/链地址法)、图(邻接表/BFS/DFS/Dijkstra/拓扑排序)、常见排序算法(快排/归并/堆排/计数排序)的实现与复杂度分析,同时分享 LeetCode 刷题技巧、竞赛编程常用模板(二分/前缀和/滑动窗口/动态规划),帮助开发者夯实算法基础。

512

2026.05.09

golang map内存释放
golang map内存释放

本专题整合了golang map内存相关教程,阅读专题下面的文章了解更多相关内容。

750

2025.09.05

Go-Zero API开发使用教程
Go-Zero API开发使用教程

本专题聚焦Go-Zero的API开发,拆解.api描述文件的语法结构、路由与分组定义、参数绑定与校验规则,说明统一响应体、JWT鉴权、跨域与接口文档生成的落地方式,并给出网关聚合与接口测试的实践建议。

100

2026.11.12

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
uni-app快速上手
uni-app快速上手

共0课时 | 0人学习

Vue 教程
Vue 教程

共42课时 | 17.5万人学习

Vue3.x 工具篇--十天技能课堂
Vue3.x 工具篇--十天技能课堂

共26课时 | 2.6万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn