讲师中心 微信公众号

工具推荐

视频效率加速
Laper
Laper

剧本策划到成片协作

updream

一键生成高质量推广成片

剧云
剧云

中文短剧剧本制作平台

AniShort
AniShort

AI短剧协同制作平台

如何基于指定键值获取Vuex状态中唯一的对象数组

落杰酱_6681

落杰酱_6681

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

|

849人浏览过

|

来源于php中文网

原创

如何基于指定键值获取vuex状态中唯一的对象数组

本文详细介绍了在Vue.js应用中,如何利用Vuex存储的数据,对一个包含重复对象的数组进行去重操作,使其基于某个特定键(如trip_class)只保留唯一的对象。文章分析了reduce方法在使用中常见的逻辑错误,并提供了正确的reduce实现方案,同时引入了更高效、简洁的Map对象去重策略,旨在帮助开发者优雅地处理数据去重需求。

在现代前端应用开发中,数据处理是核心环节之一。特别是在使用Vuex管理全局状态时,我们经常需要对从后端获取或经过处理的数据进行进一步的清洗和整理。其中,对对象数组进行去重是一个常见的需求,例如,我们可能需要从一个航班列表中,根据航班类别(trip_class)获取每个类别下的第一个航班信息,从而得到一个去重后的唯一航班类别列表。

问题阐述:如何基于特定键值对对象数组去重?

假设我们从Vuex的getters中获取到一个航班对象数组,其结构如下:

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

我们的目标是根据trip_class键进行去重,得到以下结果(保留每个trip_class的第一个出现的对象):

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

在Vue组件中,我们通常会通过计算属性(computed)来处理这类派生状态。一个常见的尝试是使用Array.prototype.reduce()方法来实现去重。

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

原始代码分析与问题诊断

以下是一个在computed属性中尝试使用reduce进行去重的示例代码:

computed: {
    flights() {
        return this.$store.getters.getFlights;
    },
    flightsClasses() {
        let flightsClasses = this.flights; // 浅拷贝或引用
        flightsClasses.reduce((acc, obj) => {
            // 错误的去重逻辑:obj.trip_class === flightClass
            var exist = acc.find((flightClass) => obj.trip_class === flightClass);
            if (!exist) {
                acc.push(obj);
            }
            return acc;
        }, []); // 初始累加器为空数组

        // 关键问题:reduce的返回值没有被赋值
        console.log('flightsClasses', flightsClasses); // 仍然是原始的、未去重的数组
        return flightsClasses;
    }
}

这段代码存在两个主要问题:

Springboot Vue Builder
Springboot Vue Builder

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

下载
  1. reduce返回值未被使用: Array.prototype.reduce()方法会返回一个新的累加器结果,但原始代码中并没有将这个返回值赋给flightsClasses变量,导致flightsClasses始终是原始的、未去重的数组。
  2. find方法中的比较逻辑错误: acc.find((flightClass) => obj.trip_class === flightClass)这一行是去重逻辑的核心。这里的flightClass是累加器acc中的一个完整对象,而obj.trip_class是一个原始值(数字)。将一个原始值与一个对象进行严格相等(===)比较,结果将永远为false。因此,find方法总是找不到匹配项,导致所有对象都被推入累加器,去重失败。

解决方案一:修正reduce方法的去重逻辑

要解决上述问题,我们需要将reduce的返回值赋给变量,并修正find方法中的比较逻辑,使其比较对象中对应的键值。

computed: {
    flights() {
        return this.$store.getters.getFlights;
    },
    flightsClasses() {
        const uniqueFlights = this.flights.reduce((acc, obj) => {
            // 修正后的去重逻辑:比较对象的特定键值
            const exists = acc.find(item => obj.trip_class === item.trip_class);
            if (!exists) {
                acc.push(obj);
            }
            return acc;
        }, []); // 初始累加器为空数组

        console.log('uniqueFlights', uniqueFlights);
        return uniqueFlights;
    }
}

解释:

  • 我们将reduce的返回值赋给了uniqueFlights常量,确保了去重后的数组被正确返回。
  • 在find方法中,我们将比较条件修改为obj.trip_class === item.trip_class。这样,find方法会正确地在累加器acc中查找是否已存在具有相同trip_class值的对象。如果不存在,则将当前对象obj推入累加器。

解决方案二:使用Map对象实现更高效的去重

对于大型数组,使用reduce配合find进行去重可能会导致性能问题,因为find在每次迭代中都需要遍历累加器。更高效的方法是利用Map对象的键唯一性特性。

computed: {
    flights() {
        return this.$store.getters.getFlights;
    },
    flightsClasses() {
        // 使用Map存储唯一的对象,键为去重依据(trip_class),值为对应的对象
        const uniqueMap = new Map();
        this.flights.forEach(flight => {
            // 如果Map中不存在该trip_class的键,则添加
            if (!uniqueMap.has(flight.trip_class)) {
                uniqueMap.set(flight.trip_class, flight);
            }
        });
        // 或者更简洁地利用Map构造函数:
        // const uniqueMap = new Map(this.flights.map(item => [item.trip_class, item]));
        // 注意:这种方式如果存在重复键,后面的会覆盖前面的,如果需要保留第一个,则需要forEach + if(!has)

        // 将Map的值(即去重后的对象)转换为数组
        const uniqueFlights = Array.from(uniqueMap.values());

        console.log('uniqueFlights (Map method)', uniqueFlights);
        return uniqueFlights;
    }
}

解释:

  • 我们创建一个新的Map实例uniqueMap。
  • 遍历原始的flights数组。
  • 对于每个flight对象,我们使用其trip_class作为Map的键,将整个flight对象作为值存入Map。
  • Map的特性是键是唯一的。如果尝试设置一个已存在的键,新的值会覆盖旧的值。为了实现“保留第一个出现”的去重逻辑,我们需要在设置之前检查Map中是否已存在该键(if (!uniqueMap.has(flight.trip_class)))。
  • 最后,使用Array.from(uniqueMap.values())将Map中存储的所有值(即去重后的对象)转换为一个新的数组。

这种Map方法的时间复杂度通常为O(N),而reduce与find结合的方法在最坏情况下可能接近O(N^2),因此Map方法在处理大量数据时表现更优。

Vuex与Computed属性的结合

在Vue中,将数据处理逻辑放在computed属性中是非常合适的。computed属性具有缓存机制,只有当其依赖项(例如this.$store.getters.getFlights)发生变化时,它才会重新计算。这确保了去重操作只在必要时执行,提高了应用性能。

注意事项

  1. 性能考量: 对于小型数组,reduce和Map两种方法在性能上差异不明显。但对于包含成千上万个对象的大型数组,强烈推荐使用Map方法,因为它提供了更优的性能。
  2. 原始数据不变性: 两种去重方法都不会修改原始的this.flights数组。它们都返回一个新的去重后的数组,这符合函数式编程的原则,有助于避免不必要的副作用和提高代码可维护性。
  3. 去重策略: 本教程中的去重逻辑是“保留第一个出现”的对象。如果需要保留最后一个出现的对象,使用new Map(this.flights.map(item => [item.trip_class, item]))这种简洁的Map构造方式即可,因为Map在键重复时会以后面的值覆盖前面的值。
  4. 键的类型: 确保用于去重的键(如trip_class)是可作为Map键的类型(原始值如字符串、数字等)。如果键是对象,需要考虑如何将其转换为唯一的字符串表示。

总结

对对象数组进行去重是前端开发中的常见任务。通过本文的讲解,我们不仅修正了reduce方法在使用中常见的逻辑错误,还引入了更高效、更简洁的Map对象去重策略。在Vuex和computed属性的配合下,这些方法能够帮助开发者以专业且高性能的方式处理数据,确保应用的数据状态始终保持整洁和准确。选择哪种方法取决于具体的场景需求和对性能的要求,但通常情况下,Map方法是处理大规模数据去重的首选。

热门AI工具

更多
小橡皮AI

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

WorkBuddy

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

DeepSeek

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

讯飞绘文

讯飞绘文是一款由科大讯飞推出的一站式 AIGC 内容运营平台。

PixPix
PixPix Hot

PixPix是一款面向电商视觉生产的AI商品图生成工具。

豆包大模型

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

UpDream
UpDream Hot

一款AI视频创作工具,主要用于哔哩哔哩推出的自研AI视频创作工具,适合需要提升相关任务效率的用户。

PixTV
PixTV Hot

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

Flowith
Flowith Hot

Flowith是一款基于画布和智能体工作流的 AI 协作工作空间。

相关专题

更多
java基础知识汇总
java基础知识汇总

java基础知识有Java的历史和特点、Java的开发环境、Java的基本数据类型、变量和常量、运算符和表达式、控制语句、数组和字符串等等知识点。想要知道更多关于java基础知识的朋友,请阅读本专题下面的的有关文章,欢迎大家来php中文网学习。

6404

2023.10.24

js 字符串转数组
js 字符串转数组

js字符串转数组的方法:1、使用“split()”方法;2、使用“Array.from()”方法;3、使用for循环遍历;4、使用“Array.split()”方法。本专题为大家提供js字符串转数组的相关的文章、下载、课程内容,供大家免费下载体验。

1938

2023.08.03

js截取字符串的方法
js截取字符串的方法

js截取字符串的方法有substring()方法、substr()方法、slice()方法、split()方法和slice()方法。本专题为大家提供字符串相关的文章、下载、课程内容,供大家免费下载体验。

3224

2023.09.04

java基础知识汇总
java基础知识汇总

java基础知识有Java的历史和特点、Java的开发环境、Java的基本数据类型、变量和常量、运算符和表达式、控制语句、数组和字符串等等知识点。想要知道更多关于java基础知识的朋友,请阅读本专题下面的的有关文章,欢迎大家来php中文网学习。

6404

2023.10.24

字符串介绍
字符串介绍

字符串是一种数据类型,它可以是任何文本,包括字母、数字、符号等。字符串可以由不同的字符组成,例如空格、标点符号、数字等。在编程中,字符串通常用引号括起来,如单引号、双引号或反引号。想了解更多字符串的相关内容,可以阅读本专题下面的文章。

6609

2023.11.24

java读取文件转成字符串的方法
java读取文件转成字符串的方法

Java8引入了新的文件I/O API,使用java.nio.file.Files类读取文件内容更加方便。对于较旧版本的Java,可以使用java.io.FileReader和java.io.BufferedReader来读取文件。在这些方法中,你需要将文件路径替换为你的实际文件路径,并且可能需要处理可能的IOException异常。想了解更多java的相关内容,可以阅读本专题下面的文章。

8134

2024.03.22

php中定义字符串的方式
php中定义字符串的方式

php中定义字符串的方式:单引号;双引号;heredoc语法等等。想了解更多字符串的相关内容,可以阅读本专题下面的文章。

12674

2024.04.29

go语言字符串相关教程
go语言字符串相关教程

本专题整合了go语言字符串相关教程,阅读专题下面的文章了解更多详细内容。

6579

2025.07.29

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.6万人学习

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

共26课时 | 2.6万人学习

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

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