【问题标题】:Fastest way to search in millions of records which is the combination of two js objects在数百万条记录中搜索的最快方法是两个 js 对象的组合
【发布时间】:2019-11-20 17:17:29
【问题描述】:

我有数百万个消息对象

messages: [
    {
      id: Int,
      text: String,
      userId: Int,
      receiverId: Int,
    },

和成千上万的用户

  users: [
    {
      id: Int,
      name: String,
    },

我需要处理两个对象并以格式返回一个对象

[{ message, userFromName, userToName }]

我读到了数组方法,例如 find、filter,其中一些和所有这些方法都比原生 for 和 foreach 慢。

我还写了两个foreach循环的函数

msgData.forEach(function(msg,i) {
    ...iterating every msg 
    userData.forEach(function(user) {
       ...iterating every user id over message sender and receiver id
    });
});

代码复杂度O(n)square

如何在更短的时间内获得所需的格式?

【问题讨论】:

  • 如果你让服务器处理这些数据,也许效率会更高。
  • 如果您的数据可以转换为以 id 为键的对象,例如 messages = {"id1": {...}, "id2": {...}}users = {"id1": {...}, "id2": {...}},那么您可以大大提高性能,因为现在由对象键完成查找,而不是迭代通过一个数组。
  • 我需要处理两个对象” - 哪些? “并以格式返回一个对象” - 你的意思是返回一个包含多个对象的数组吗?
  • 是什么让你认为findsomeforEach 慢?
  • 把它们放在几个Maps中:消息由发送者键入,消息由接收者键​​入,用户由id键入。这应该可以让您足够高效地进行大多数搜索。

标签: javascript ecmascript-6 time-complexity javascript-objects


【解决方案1】:

users 转换为字典以实现快速、非迭代查找:

原生对象:

let userDict = users.reduce((o,u)=> {
  o[u.id]=u.name;
  return o;
}, {});

地图:

let userDict = new Map();
userDict.forEach(u => userDict.set(u.id,u.name));

这是 O(n)。使用此字典,您可以将 msgData forEach 简化为:

let result = msgData.map(msg => {
  return { message: msg.text, userFromName: userDict[msg.userId], userToName: userDict[msg.receiverId]};
 });

这也是 O(n),因为对象和 Map 查找都是 O(1)。有关这些性能的详细信息,请参阅this question。无论采用哪种方式,都将比您当前的 O(n^2) 解决方案显着提高性能。

【讨论】:

    【解决方案2】:

    假设你将在两个数组之间有一个共同的键,你可以使用哈希映射数据结构,在 Javascript 中可以表示为一个简单的普通对象,例如:

    const users = [{id: 1, name: 'Marcela'}, {id:2, name: 'Ana'}];
    const messages = [{id: 1, message: 'She is a great Graphic Designer'}, {id: 2, message: 'She likes watch movies'}];
    
    // #1 convert one array to a hashmap
    const userHashMap = {};
    
    // O(N)
    for (let user of users) {
      userHashMap[user.id] = user;
    }
    
    // above code will store a DS like 
    // {
    //     1: 
    //         {
    //             id: 1,
    //             name: 'Marcela'
    //         }, 
    //     2:
    //         {
    //             id: 2,
    //             name: 'Ana'
    //         }
    // }
    
    // #2 Now you can iterate over messages in O(N)
    // and we can get the values of users 
    // in constant time O(1) (That's the most important use of HashMaps):
    
    messages.forEach(message => {
      console.log(`This id message ${message.id} belongs to ${userHashMap[message.id].name}`);
      console.log(`Message for ${userHashMap[message.id].name}: ${message.message}`);
    });

    请记住,我们使用一种对内存有影响的技术来降低时间复杂度(对象 HashMap 为每个用户存储数据,因此空间复杂度为 O(N))。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-08-10
      • 2021-03-15
      • 2021-08-07
      • 2011-08-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多