Set,Map数据类型,ES6 数组方法在项目中的实际应用

215 阅读3分钟

一. 问题描述

  最近在开发一个需求,有段内容是一个只读输入框点击后弹出一个产品列表框,选择完产品后将产品名称回显到输入框上。有趣的地方在于,要向两个接口请求数据,接口A返回全量数据,格式为{ prodId,prodName,... },接口B返回存量数据,格式为{ prodId,lableId,creatDate,... },接口A的数据用于渲染列表显示,接口B若不为空,则要求A中对应prodId的产品处于选中状态。当提交时,要向接口C发送数据,addList里面放本次操作添加的数据,delList放本次操作删除的数据,数据格式为{ prodId,lableId,...}。三种接口数据格式均有差异,但是prodId是对应的,要求前端做好数据处理。

二.解决方案

  碰到的第一个问题就是存量数据的名称回显,存量数据中并没有prodName这个属性,需要通过prodId到全量数据中拿出来再拼接成字符串。最初的方案如下

// 全量数据列表
const allMeasuredDataList = [
    { prodId: '1', prodName: '产品1' },
    { prodId: '2', prodName: '产品2' },
    { prodId: '3', prodName: '产品3' },
    { prodId: '4', prodName: '产品4' },
    { prodId: '5', prodName: '产品5' },
]

// 存量数据列表
const inventoryDataList = [
    { prodId: '2', labelId: '233' },
    { prodId: '5', labelId: '23' },
    { prodId: '3', labelId: '33' },
]

let prodName = ""
inventoryDataList.forEach(inventoryInfo => {
    allMeasuredDataList.forEach(allMeasured => {
        if (inventoryInfo.prodId === allMeasured.prodId) { 
            prodName = prodName + allMeasured.prodName + " "
        }
    })
})

console.log(prodName) // 产品2 产品5 产品3 ;

确实是实现了效果,但是若全量有N条数据,存量有M条数据,总循环数为N*M次,肯定是不理想。将里层的forEach换成find的话,可以减少一定的循环次数,但还是嵌套循环,不是要考虑的方向。因为存量永远是全量的子集,考虑将子集的prodId存入set都对象中,用空间换时间,减少循环次数。

const prodList = inventoryDataList.map(inventoryInfo => inventoryInfo.prodId)
const prodIdSet = new Set(prodList)
const prodName = allMeasuredDataList.reduce((prodName, allMeasuredInfo) => {

    return (
        prodIdSet.has(allMeasuredInfo.prodId)
            ? prodName + allMeasuredInfo.prodName + " "
            : prodName
    )
}, '')
console.log(prodName) // 产品2 产品5 产品3 ;

可以看到依旧是可以实现效果的,将嵌套的循环分开,总循环次数为 N+M 次,但是因为M永远是N的子集,所以应该是将全量数据存到一个Map里面,然后存量到全量里面找,因此

const prodIdToProdNameList = allMeasuredDataList.map(allMeasuredInfo => {
    const { prodId, prodName } = allMeasuredInfo
    
    return [prodId, prodName]
})
const prodIdToProdNameMap = new Map(prodIdToProdNameList)
const prodName = inventoryDataList.map(inventoryInfo => {
    return prodIdToProdNameMap.get(inventoryInfo.prodId)
}).join(' ')
console.log(prodName) // 产品2 产品5 产品3 ;

可以看到,也是可以实现功能,到此,prodId转prodName的方案算是结束了。

  第二个问题是数据的增减对比,需要有一个数组存checkList来存放选中的所有数据,然后与存量数据进行对比,存量有,当前无,则该产品被删除,存量无,当前有,则该产品为新增。开始代码编写

// 当前选取的数据
const checkList = [
    { prodId: '1', prodName: '产品1' },
    { prodId: '2', prodName: '产品2' },
    { prodId: '3', prodName: '产品3' },
    { prodId: '4', prodName: '产品4' },
    { prodId: '5', prodName: '产品5' },
]

//存量数据列表
const inventoryDataList = [
    { prodId: '8', labelId: '233' },
    { prodId: '5', labelId: '23' },
    { prodId: '7', labelId: '33' },
]

const addList = checkList.filter(checkInfo => {
    return !inventoryDataList.some(inventoryInfo => checkInfo.prodId === inventoryInfo.prodId)
})

const delList = inventoryDataList.filter(inventoryInfo => {
    return !checkList.some(checkInfo => checkInfo.prodId === inventoryInfo.prodId)
})

console.log("add:",addList, "del:",delList);
 /* 
 add:[
  { prodId: '1', prodName: '产品1' },
  { prodId: '2', prodName: '产品2' },
  { prodId: '3', prodName: '产品3' },
  { prodId: '4', prodName: '产品4' }
] 
del: [ { prodId: '8', labelId: '233' }, { prodId: '7', labelId: '33' } ]
*/

可以看到,正确的筛选出的增删的数据,至此,功能实现。

总结

  利用Set和Map对象,可以在需要的时候,用内存空间来换取更快的运行时间,灵活运用数组方法,可以便捷的去处理数据,提升工作效率,从而增加摸鱼时间。