0

I'm asking little naive question, but I'm seriously I'm not sure how to convert this for loops

const filteredData = csiList.filter(item => {
        for (var i = 0, len = this.tableData.length; i < len; i++) {
          if (this.tableData[i].csiId == item.appId) {
            return false;
          }
        }
        return true;
      })

If some one can quickly show how this loops are/is written in more next gen JS ES6/ES7 way, would be of great help

Kriti
  • 9
  • 3
  • `this.tableData` is an array, right? (as opposed to an [array-like](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Indexed_collections#working_with_array-like_objects) object) – Samathingamajig Aug 16 '23 at 17:31
  • [Array.prototype.some](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/some) – kelsny Aug 16 '23 at 17:34
  • Consider using [`some`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/some) instead of a for loop inside a filter? – evolutionxbox Aug 16 '23 at 17:35
  • @Samathingamajig Yes its an array – Kriti Aug 16 '23 at 17:39

3 Answers3

2

There are a lot of ways to make this more modern code, each step I show here is a based upon the previous:

#1 Use for...of loops instead of manually using an index variable (also use const since this never changes during the same iteration)

const filteredData = csiList.filter((item) => {
  for (const data of this.tableData) {
    if (data.csiId == item.appId) {
      return false;
    }
  }
  return true;
});

#2 Use Destructuring to just get the necessary data (this is an opinion of if it's better or not, but I'm using more modern features since that's what you have asked for)

const filteredData = csiList.filter(({ appId }) => {
  for (const { csiId } of this.tableData) {
    if (csiId == appId) {
      return false;
    }
  }
  return true;
});

#3 Use Array.prototype.some, built for finding if at least one item in a list meets a criteria. Inverted here with !, since it returns true if at least one items meets the criteria. (Alternatively, use every with !==)

const filteredData = csiList.filter(({ appId }) => {
  return !this.tableData.some(({ csiId }) => csiId === appId);
});

#4 Use the implicit return of an arrow function with { and } (on a new line because the width of each line is limited to 80 characters by Prettier's opinionated standard)

const filteredData = csiList.filter(
  ({ appId }) => !this.tableData.some(({ csiId }) => csiId === appId),
);
Samathingamajig
  • 11,839
  • 3
  • 12
  • 34
0

I'm not sure how big your lists are but the solution using .some is O(mn). Meaning you're cycling through your tableData list multiple times.

Faster would be using a Set(). This solution would be O(n).

(() => {

const tableData = [{ csiId: 1 }, { csiId: 2 }, { csiId: 4 }];
const csiList = [{ appId: 1 }, { appId: 3 }, { appId: 4 }];

const keepers = new Set(tableData.map((data) => data.csiId));
const filteredData = csiList.filter((obj) => keepers.has(obj.appId));
    
console.log(filteredData);

})();
twalow
  • 405
  • 3
  • 6
  • It's worth mentioning that using a set is generally not faster for small arrays (iterating through is faster than hashing and lookup) or when you're not using the set enough times (when creating the set is more expensive than just using the list), however this is probably on the scale of Doesn't Matter™. Remember, big o tells you the shape of how a function scales in space/time as input increases, it doesn't tell you what algorithm is faster for a certain number of inputs. – Samathingamajig Aug 16 '23 at 18:18
  • That's why I stated at top "I'm not sure how big your lists are". – twalow Aug 16 '23 at 18:19
  • This topic is covered in depth on here: https://stackoverflow.com/questions/39007637/javascript-set-vs-array-performance – twalow Aug 16 '23 at 18:26
-1
const filteredData = csiList.filter(item => !this.tableData.some(tableDataItem => tableDataItem.csiId === item.appId));
Jared Smith
  • 19,721
  • 5
  • 45
  • 83