在javascript中查找映射到某个值的所有键。高效的替代方案

在javascript中查找映射到某个值的所有键。高效的替代方案,javascript,object,search,types,key,Javascript,Object,Search,Types,Key,我正在用javascript开发一个应用程序,每个用户都在一个房间里。没有两个用户共享相同的名称,也没有两个房间共享相同的名称。目前我将其设置为: var userroommap = { username: "room", username2: "room", username3: "room2" } 获取用户所在的房间非常简单 userroommap["user"] 但是为了获得房间中的所有用户,我必须像这样迭代整个userroommap: for (var x in user

我正在用javascript开发一个应用程序,每个用户都在一个房间里。没有两个用户共享相同的名称,也没有两个房间共享相同的名称。目前我将其设置为:

var userroommap = {
  username: "room",
  username2: "room",
  username3: "room2"
}
获取用户所在的房间非常简单

userroommap["user"]
但是为了获得房间中的所有用户,我必须像这样迭代整个userroommap:

for (var x in userroommap) {
  if (userroommap[x] == "room")
    //user x is present in room 
  }
}
在我的应用程序中,我必须经常知道哪些用户在哪些房间,因此我考虑使用另一个对象来容纳房间中的所有用户,例如:

var roomusermap = {
  room:["username", "username2"],
  room2:["username3"]
}

将用户添加到文件室很简单,因为您所要做的只是将其附加到一个数组中,但是从文件室中删除用户名需要迭代该数组,这将是一个不错的操作。对于我的问题,这已经是一个不错的解决方案,但我开始好奇是否有更好的解决方案。那么:有没有更好的方法来(i)存储roomusermap,也许没有数组?或者,或者(ii)在一个房间中查找所有用户?

除非您确定了一个真正的、真实的性能问题,否则我将坚持使用简单的解决方案

也就是说,给你一些想法:

  • 所有现代JavaScript引擎都提供了
    Object.keys
    函数,该函数返回对象自身可枚举属性的数组。这可能比您的
    循环中更有效,原因有两个:

  • 它发生在引擎代码中,让引擎优化

  • for in
    在原型对象中查找可枚举属性,而
    Object.keys
    知道它只应该在该特定对象中查找

  • 您的
    roomusermap
    可以包含每个房间的地图,它不需要使用数组

    var roomusermap = {
        room: {
            username: user,
            username2: user2
        },
        room2: {
            username3: user3
        }
    };
    
    将用户添加到文件室将变成:

    userroommap[username] = roomname;
    roomusermap[roomname][username] = user;
    
    删除用户是:

    delete userroommap[username];
    delete roomusermap[roomname][username];
    
  • 如果您看到这些映射对象存在性能问题,请记住,从对象中删除属性(
    delete
    )会使对象在几个JavaScript引擎上进入“字典模式”(以前处于更优化的状态),显著影响在该对象上查找属性所需的时间

    因此,在假定属性查找性能开始成为问题的假设情况下,可以考虑存储<代码>未定义,而不是删除该属性。例如,代替:

    delete userroommap[username];
    delete roomusermap[roomname][username];
    
    你会的

    userroommap[username] = undefined;
    roomusermap[roomname][username] = undefined;
    
    但是,您必须调整对用户是否在房间中的检查,并且您不能再使用
    Object.keys
    (单独)来获取列表,因为您必须删除值
    未定义的属性。您可以将
    Object.keys
    filter
    一起使用:

    var map = roomusermap[roomname];
    var users = Object.keys(map).filter(function(username) {
        return map[username] !== undefined;
    });
    
    因此,只有当您确定了对象进入字典模式所导致的真正问题时,您才会真正希望这样做


上一个答案中描述的数据结构称为BiMap

BiMap理想情况下为
value:keys
查找操作提供与
key:values
查找相同的性能。它通常通过内部管理两个单独的映射来实现(一个具有正向映射
{key:values}
,另一个具有反向映射
{value:keys}


如果您不使用自己的实现,可以使用下面的现有实现

使用对象有什么问题?您是否看到了真正的性能问题?我想我只是好奇是否有某种方法可以实现我没有列出的值:键。但是你的评论让我意识到这是一个没用的问题:/也许不是一个没用的问题,这很有帮助,谢谢。