首页 >web前端 >js教程 >稍微好一点的'地图”可以让你更轻松地到达那里......

稍微好一点的'地图”可以让你更轻松地到达那里......

Barbara Streisand
Barbara Streisand原创
2024-12-09 08:33:12374浏览

A slightly better

在 JavaScript 中,Map 是一个非常有用的内置类,它在键和值之间创建 O(1) 查找。

const myMap = new Map()

for(const file of files) {
    const [,extension] = file.name.split(".")
    if(!myMap.has(extension)) {
        myMap.set(extension, [])
    }
    myMap.get(extension).push(file)
}

您可以使用地图来完成您可能经常做的各种事情:

  • 创建数据分组列表,如上面按文件扩展名分组的示例

  • 聚合数据,例如对一系列键的值进行计数或求和

// 1) Counting occurrences
const items = ['apple','apple','orange','banana','apple'];
const counts = new Map();
for (const item of items) {
  counts.set(item, (counts.get(item) || 0) + 1);
}
  • 创建在后续步骤中使用的快速查找
const users = [
  {id:1,name:'A',role:'admin'},
  {id:2,name:'B',role:'user'},
  {id:3,name:'C',role:'user'}
];
const userMap = new Map();
for (const u of users) {
  userMap.set(u.id, u);
}

Map 优于使用简单对象 ({}),原因有几个,只要您不必使用 stringify 存储结果:

  • 它可以采用非字符串的键
  • 即使您使用字符串键,它也比对象稍快

但是,如果您存储在映射中的对象需要构造(从简单数组到复杂对象),则可能会有很多样板文件和混合问题,这需要散布在使用它的代码中.

const map = new Map()

for(const item of items) {
   if(!map.has(item.type)) {
       const newType = new Type(item.type, getInfoForType(item.type))
       map.set(item.type, newType)
   }
   map.get(item.type).doSomething(item)

}

这个“可以”是可以的,但是如果你需要在多个地方更新或初始化值,那么保持 DRY 就变得更困难。

出于这个原因,我使用了 MapPlus 类,它是 Map 的扩展,它提供了一个缺失的键初始化函数,可以将其提供给构造函数,或者如果初始化程序确实需要上下文信息之外的信息,则可以将其作为 get 的第二个参数钥匙。

class MapPlus extends Map {
    constructor(missingFunction) {
        super()
        this.missingFunction = missingFunction
    }

    get(key, createIfMissing = this.missingFunction) {
        let result = super.get(key)
        if (!result && createIfMissing) {
            result = createIfMissing(key)
            if (result && result.then) {
                const promise = result.then((value) => {
                    super.set(key, value)
                    return value
                })
                super.set(key, promise)
            } else {
                super.set(key, result)
            }
        }
        return result
    }
}

有了这个你就可以做这样的事情:

const map = new MapPlus(()=>[])

for(const item of items) {
    map.get(item.type).push(item)
}

就像缺少键一样,它只会生成一个空数组。

我经常需要两个级别,所以我将像这样定义地图:

const map = new MapPlus(()=>new MapPlus(()=>[]))
for(const item of items) {
   map.get(item.type).get(item.subType).push(item)
}

构造函数确实获取了正在使用的密钥,因此我们也可以这样做:

const map = new MapPlus((type)=>new Type(type, getInfoForType(type))

for(const item of items) {
    map.get(item.type).doSomething(item)
}

以上是稍微好一点的'地图”可以让你更轻松地到达那里......的详细内容。更多信息请关注PHP中文网其他相关文章!

声明:
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn