skip to Main Content

is there more efficient to getting list of object that contain same property as listed in the array

  let x = [{
    name: "Apple",
    message: {
      data: {}
    }
  },
  {
    name: "Alienware",
    message: {
      data: {price: 20 }
    }
  },
  {
    name: "dell",
    message: {
      data: {}
    }
  },
  {
    name: "samsung",
    message: {
      data: {}
    }
  },
  {
    name: "Alienware",
    message: {
      data: {price: 25 }
    }
  }
];

let nameToCheck = ["HP", "Apple", "Nvidia", "Lenovo", "Acer", "Asus", "Alienware"];
let dataFound = [];

let nameList = {}
x.forEach((element, index) => {
  nameList[element.name] = index
})

nameToCheck.forEach((element, index) => {
  if (nameList[element] != undefined) {
    dataFound.push(x[nameList[element]])
  }
})

console.log(dataFound)

The array nameToCheck can be any data structure.

What i am trying to do is extract the objects that matches with the list of string and that in efficient way in time.

This operation need to happen in very high frequency might be around 40 times a second and list of nameToCheck is bigger array most probably size of 50.

Is there more time efficient way to do this ? or more nice way of doing this ?

3

Answers


  1. more clear way which achieve the same thing (Set is also indexed so its fast)

    let x = [{
        name: "Apple",
        message: {
          data: {}
        }
      },
      {
        name: "dell",
        message: {
          data: {}
        }
      },
      {
        name: "samsung",
        message: {
          data: {}
        }
      }
    ];
    
    let nameList = new Set(["HP", "Apple", "Nvidia"]);
    let dataFound = x.filter(el => nameList.has(el.name))
    
    
    console.log(dataFound)

    btw. in your code you don’t handle cases where you have two items of the same company

    Login or Signup to reply.
  2. You can use a Set to store the names to check for. Now all you need to do it just filter the data.

    const data = [
      { name: "Apple"   , message: { data: {} } },
      { name: "Dell"    , message: { data: {} } }, 
      { name: "Samsung" , message: { data: {} } }
    ];
    
    const nameToCheck = new Set(["HP", "Apple", "Nvidia"]);
    
    const dataFound = data.filter(({ name }) => nameToCheck.has(name));
    
    console.log(dataFound);

    Result:

    [
      {
        "name": "Apple",
        "message": {
          "data": {}
        }
      }
    ]
    
    Login or Signup to reply.
  3. Well, instead of storing indices, you could group them by the name

    let x = [{name: "Apple", message: {data: {}}},
             {name: "dell", message: {data: {}}}, 
             {name: "samsung", message: {data: {}}}
            ];
            
    const groupedX = x.reduce((acc, item) => {
      acc[item.name] = item;
      return acc;
    }, {});
    
    let nameToCheck = ["HP", "Apple", "Nvidia"];
    let dataFound = [];
    
    nameToCheck.forEach((name) => {
      const group = groupedX[name];
      if (group) {
        dataFound.push(group)
      }
    })
    
    console.log(dataFound)

    Also depending on how critical the loop is you could convert both reduce and forEach to simple loops which are normally faster.


    If you have to recreate the nameToCheck on each iteration, then you could use an object instead of a Set and a filter for the fastest combo.

    let x = [
        {name: "Apple", message: {data: {}}},
        {name: "dell", message: {data: {}}}, 
        {name: "samsung", message: {data: {}}},
    ];
    const nameToCheck = {"HP":true, "Apple":true, "Nvidia":true};
    
    
    const dataFound = x.filter(company => nameToCheck[company.name]);
    
    console.log(dataFound);

    See https://jsbench.me/g7lm7yni2p/1 for comparison

    (keep in mind that result can change if you extract parts outside of the critical loop)
    (also keep in mind that results will vary, a lot in some cases, between browsers)

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search