通过Map结构数据来处理业务逻辑中的response data?

在业务开发过程中,会有很大概率在与后台对接数据的时候,遇到这种数据格式

{
  ...
  data: [
    {
      ...
      id: 10000,
      name: '中国电信',
      ...
    },
  ],
  ...
}

假设我们已经将这个data渲染为一个列表,然后现在有一个需求:在一个Input组件中输入id,之后对data中对应的id那一项进行某些业务处理。
按之前的习惯,就直接这样了

// 处理Input组件输入事件
handleInput(id) {
  data.forEach(item => {
    if(item.id === id) {
    // 拿到item,然后处理业务逻辑
    }
  })
}

但是这样的话感觉每次都得将整个data遍历一遍,感觉太浪费性能了。
所以在想可不可以用Map来处理一下,比如

// 将data转换成类似Map的数据结构,或者new Map()貌似也可以?
toMap(data, mainKey = 'id') {
  const map = {};
  data.forEach(item => {
    map[mainKey] = item;
  });
  return map;
}

const map = toMap(data);

这样转换之后,后续就可以在handleInput(id)方法中直接用map[id]或者如果使用Map的话map.get(id)来获取到对应的item了。不知道这样做在实际的业务开发中是否具有可行性。。。

阅读 3.8k
4 个回答

我并不清楚 js,所以我从 c/c++ 的角度回答下。

用 map 是个不错的选择,首先复杂度就已经从 n 降到 logn 了,如果你的数据量级在上千以上的话,可以作个测试,比对下 n和 logn 的时间差距(量级越大,差距越大)。

再者,就是你用了 map 后的这句代码,

data.forEach(item => {
    map[mainKey] = item;
  });

其中的forEach,我不清楚 js 是怎么实现的,至少在 map 中如果你要根据 key 找一个数据,应该用这个 map 提供的类似find的接口,这个接口的实现复杂度是 logn。

forEach,它实现的机制,可能是中序遍历(利用左右孩子指针,具体参考线索二叉树),也就是说,它的查找复杂度是 n,一般用这种方法的目的,就是按序输出所有数据。

所以,js 的 map 容器的接口,是用 find这种的,还是forEach,得去看文档说明,或者谷歌,看下它们具体的内部实现机制。

-----------------------------分割-----------------

看了下上面的回答,如果你的 data 可以 O(1) 索引取值的话,建一个哈希映射也可以,但内存的代价自己估量,我说的哈希不是用 map,它是一个整型数组,把 id 作为数组下标,data 索引作为数组的值。

可以啊,但是你写的都太麻烦了

  • 过滤直接用`filter:

    [{id:1, name:'1'},{id:2, name:'2'}].filter(({id})=>id===1)
  • 转化直接用map

[{id:1, name:'1'},{id:2, name:'2'}].map(d=>({[d.id]:d}))

```
  • 写成公用的toMap

    function toMap(data, key){
       return data.map(d=>({[d[key]]:d}))
    }
  • 想要获取原始列表:

    Object.values(toMap(data))

data.some(item => {

if(item.id === id) {
   //业务逻辑
 return true
}

})

既然是列表,那为什么不传 索引 呢?知道是第几项不就行了,没必要再循环一遍

// 处理Input组件输入事件
handleInput(i) {
  data[i]
}
撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题