skip to Main Content

I have been racking my brain on how to filter through an array with multiple criteria. I kept looking online, but there was always at least one factor that made the solution not work for my array and use case.

I have a large nested array that I need to filter down by two criteria:

Criteria 1: if there are no duplicates in the client name elements (testArray[i][1]) then add keep in array

Criteria 2: if there are duplicates in the client name elements (testArray[i][1]) and those duplicates do not have duplicate product codes (testArray[i][2]) then keep all records with the same client name elements, but only keep the first records with unique product codes (testArray[i][2]).

Here is a sample array so I don’t give out client info:

let testArray = [
  ["ASDF245", "Jeff Hill", "BOP"],
  ["ASCG285", "Jerry F Tate", "BOP"],
  ["ASDF240", "Jeff Hill", "WC"],
  ["ASDF291", "Jake Sab", "BOP"],
  ["ASDF301", "Mary Stein", "WC"],
  ["ASDF460", "Jeff Hill", "WC"],
  ["ASDF245", "Hello Dup", "BOP"],
  ["ASDF245", "Hello Dup", "BOP"],
  ["ASDF245", "Hello Dup", "WC"]
];

I have tried using nested for loops, filter functions, foreach functions, etc. I can always get them to get through the first criteria, but not the second. This is one of my latest attempts:

  let newArray = [];
  for (let b = 0; b < testArray.length; b++) {
    newArray.push(["s","s","s"]);
  }
  let count = 0;
  let tempArrayOne = [];
  let tempArrayTwo = [];
  for (let i = 0; i < testArray.length; i++) {
    for (let j = 0; j < testArray.length; j++) {
      if (testArray[i][1] == testArray[j][1]) {
        count++;
      }
    }
    if (count == 1) {
      newArray.push(testArray[i])
    }
    if (count > 1) {
      Logger.log(testArray[i][1]);
      tempArrayOne = testArray.filter((iTwo, jTwo) => {
        if (iTwo[1] == testArray[i][1]) {
          return iTwo[jTwo];
        }
      })
      Logger.log(tempArrayOne)
      //Logger.log(tempArrayTwo.findIndex((item) => {return item[1] == tempArrayOne[0][1]}));
      //Logger.log(tempArrayTwo);
      if (tempArrayTwo.findIndex((item) => {return item[1] == tempArrayOne[0][1]}) == -1.0) {
        //for(let s = 0; s < tempArrayOne)
        newArray = [...newArray, ...tempArrayOne];
        tempArrayTwo = [...tempArrayTwo, ...tempArrayOne];
      }
    }
    count = 0;
    Logger.log(newArray);
  }
  newArray.splice(0, testArray.length);
  Logger.log(newArray);

I feel super dumb because I think I am just overthinking the solution. For some reason, the filter function works on the first duplicate ("Jeff Hill"), but it doesn’t work on the second duplicate ("Hello Dup"). For "Hello Dup" it just makes tempArrayOne an empty array, thus making the whole function pull an error.

2

Answers


  1. Objects in JavaScript are your friend when it comes to removing duplicates. All you need to do is come up with the right key — in your case the name and the product.

    let testArray = [
      ["ASDF245", "Jeff Hill", "BOP"],
      ["ASCG285", "Jerry F Tate", "BOP"],
      ["ASDF240", "Jeff Hill", "WC"],
      ["ASDF291", "Jake Sab", "BOP"],
      ["ASDF301", "Mary Stein", "WC"],
      ["ASDF460", "Jeff Hill", "WC"],
      ["ASDF245", "Hello Dup", "BOP"],
      ["ASDF245", "Hello Dup", "BOP"],
      ["ASDF245", "Hello Dup", "WC"]
    ];
    
    const dict = {};
    testArray.forEach(([id, name, product]) => 
      dict[`${name}-${product}`] ||= [id, name, product]);
      
    console.log(Object.values(dict));
    Login or Signup to reply.
  2. You can use Set to keep track of unique pairs, in the most cases it’s faster than an object. The more items the more is difference.

    const set = new Set;
    const result = testArray.filter(item => {
      const key = item[1] + item[2];
      return !set.has(key) && set.add(key);
    });
      
    result.forEach(item =>console.log(...item));
    <script>
    let testArray = [
      ["ASDF245", "Jeff Hill", "BOP"],
      ["ASCG285", "Jerry F Tate", "BOP"],
      ["ASDF240", "Jeff Hill", "WC"],
      ["ASDF291", "Jake Sab", "BOP"],
      ["ASDF301", "Mary Stein", "WC"],
      ["ASDF460", "Jeff Hill", "WC"],
      ["ASDF245", "Hello Dup", "BOP"],
      ["ASDF245", "Hello Dup", "BOP"],
      ["ASDF245", "Hello Dup", "WC"]
    ];
    </script>
    ` Chrome/117
    -----------------------------------------------------
    Alexander   1.0x  |  x100000  182  186  187  191  194
    Christian   2.5x  |  x100000  463  466  472  480  484
    -----------------------------------------------------
    https://github.com/silentmantra/benchmark `
    
    let testArray = [
      ["ASDF245", "Jeff Hill", "BOP"],
      ["ASCG285", "Jerry F Tate", "BOP"],
      ["ASDF240", "Jeff Hill", "WC"],
      ["ASDF291", "Jake Sab", "BOP"],
      ["ASDF301", "Mary Stein", "WC"],
      ["ASDF460", "Jeff Hill", "WC"],
      ["ASDF245", "Hello Dup", "BOP"],
      ["ASDF245", "Hello Dup", "BOP"],
      ["ASDF245", "Hello Dup", "WC"],
      ["ASDF245", "Jeff Hill", "BOP2"],
      ["ASCG285", "Jerry F Tate", "BOP2"],
      ["ASDF240", "Jeff Hill", "WC2"],
      ["ASDF291", "Jake Sab", "BOP2"],
      ["ASDF301", "Mary Stein", "WC2"],
      ["ASDF460", "Jeff Hill", "WC2"],
      ["ASDF245", "Hello Dup", "BOP2"],
      ["ASDF245", "Hello Dup", "BOP2"],
      ["ASDF245", "Hello Dup", "WC2"],
      ["ASDF245", "Jeff Hill", "BOP3"],
      ["ASCG285", "Jerry F Tate", "BOP3"],
      ["ASDF240", "Jeff Hill", "WC3"],
      ["ASDF291", "Jake Sab", "BOP3"],
      ["ASDF301", "Mary Stein", "WC3"],
      ["ASDF460", "Jeff Hill", "WC3"],
      ["ASDF245", "Hello Dup", "BOP3"],
      ["ASDF245", "Hello Dup", "BOP3"],
      ["ASDF245", "Hello Dup", "WC3"],
      ["ASDF245", "Jeff Hill", "BOP4"],
      ["ASCG285", "Jerry F Tate", "BOP4"],
      ["ASDF240", "Jeff Hill", "WC4"],
      ["ASDF291", "Jake Sab", "BOP4"],
      ["ASDF301", "Mary Stein", "WC4"],
      ["ASDF460", "Jeff Hill", "WC4"],
      ["ASDF245", "Hello Dup", "BOP4"],
      ["ASDF245", "Hello Dup", "BOP4"],
      ["ASDF245", "Hello Dup", "WC4"]
    ];
    
    // @benchmark Christian
    const dict = {};
    testArray.forEach(([id, name, product]) => 
      dict[name + '-' + product] ||= [id, name, product]);
    Object.values(dict);
    
    // @benchmark Alexander
    const set = new Set;
    testArray.filter(item => {
      const key = item[1] + item[2];
      return !set.has(key) && set.add(key);
    });
     
    /*@end*/eval(atob('e2xldCBlPWRvY3VtZW50LmJvZHkucXVlcnlTZWxlY3Rvcigic2NyaXB0Iik7aWYoIWUubWF0Y2hlcygiW2JlbmNobWFya10iKSl7bGV0IHQ9ZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgic2NyaXB0Iik7dC5zcmM9Imh0dHBzOi8vY2RuLmpzZGVsaXZyLm5ldC9naC9zaWxlbnRtYW50cmEvYmVuY2htYXJrL2xvYWRlci5qcyIsdC5kZWZlcj0hMCxkb2N1bWVudC5oZWFkLmFwcGVuZENoaWxkKHQpfX0='));
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search