skip to Main Content

I have data from a form that needs to be compared to its older data.
I want to check if an object was in the previous old data and if its slot number changed.

Data example

const oldData = [{name: "John", slot: 2}, {name: "John", slot: 3}, {name: "John", slot: 4}]
const newData = [{name: "Alex", slot: 2}, {name: "John", slot: 3}, {name: "Bob", slot: 4}, {name: "John", slot: 5}]

  // Duplications
  const duplicateCreate = newData.filter((order1) => {
    return oldData.some((order2) => {
      return (
        order1.name === order2.name &&
        order1.slot !== order2.slot
      );
    });
  });

  console.log(duplicateCreate)

What I expect the output to be

[{name: "John", slot: 5}] 

What I get

[{name: "John", slot: 3}, {name: "John", slot: 5}] 

I have no Idea why the some function is passing john slot 2 as truthy, if I change my code to
order1.slot === order2.slot then the output will be

[{name: "John", slot: 3}] 

So clearly its reading the && condition and clearly that logic works but the logic of checking for the object whose name is john and slot !== the same isnt working the way its written from my understanding so I am kind of at a loss right now.

3

Answers


  1. I ran a couple of scenarios and this works fine:

    const oldData = [{name: "John", slot: 2}, {name: "John", slot: 3}, {name: "John", slot: 4}];
    const newData = [{name: "Alex", slot: 2}, {name: "John", slot: 3}, {name: "Bob", slot: 4}, {name: "John", slot: 5}];
    
    const duplicateCreate = newData.filter((order1) => {
      const exactMatch = oldData.some(order2 => order1.name === order2.name && order1.slot === order2.slot);
      const nameMatch = oldData.some(order2 => order1.name === order2.name);
    
      return nameMatch && !exactMatch;
    });
    
    console.log(duplicateCreate);  // [{name: "John", slot: 5}]
    

    Edit: Explanation

    Original Code:
    For each item in newData, it checks if there’s an item in oldData with the same name but a different slot. This approach leads to false positives, like including {name: "John", slot: 3}, since there’s another "John" in oldData with a different slot.

    Revised Code:
    For each item in newData, it checks two things:

    • If there’s an exact match in `oldData (both name and slot).
    • If there’s a name match in oldData (just the name). The item from newData is included in the result only if there’s a name match but not an exact match. This ensures that only true duplicates (same name, different slot, and no exact match in oldData) are included in the result.
    Login or Signup to reply.
  2. Same as jagmitg, failed to convert to single check. But, it will be a bit more optimal in speed due to exiting the calculation on first .some:

      const duplicateCreate = newData.filter((order1) => {
        return oldData.some((order2) => {
          return (
            order1.name === order2.name 
          ) 
        }) && !oldData.some((order2) => {
            return (
            order1.name === order2.name && order1.slot === order2.slot)
        })
      });
    
    Login or Signup to reply.
  3. There’s no need to check all conditions in jagmitg’s solution:

    const oldData = [{name: "John", slot: 2}, {name: "John", slot: 3}, {name: "John", slot: 4}];
    const newData = [{name: "Alex", slot: 2}, {name: "John", slot: 3}, {name: "Bob", slot: 4}, {name: "John", slot: 5}];
    
    const duplicateCreate = newData.filter((order1) => {
      const nameMatch = oldData.some(order2 => order1.name === order2.name);
      if(!nameMatch) return;
      return !oldData.some(order2 => order1.name === order2.name && order1.slot === order2.slot);
    });
    
    console.log(duplicateCreate);

    And a benchmark:

    enter image description here

    <script benchmark data-count="10000000">
    
        const oldData = [{name: "John", slot: 2}, {name: "John", slot: 3}, {name: "John", slot: 4}];
        const newData = [{name: "Alex", slot: 2}, {name: "John", slot: 3}, {name: "Bob", slot: 4}, {name: "John", slot: 5}];
    
    // @benchmark jagmitg
    
    newData.filter((order1) => {
      const exactMatch = oldData.some(order2 => order1.name === order2.name && order1.slot === order2.slot);
      const nameMatch = oldData.some(order2 => order1.name === order2.name);
      return nameMatch && !exactMatch;
    });
    
    
    // @benchmark Alexander
    
    newData.filter((order1) => {
      const nameMatch = oldData.some(order2 => order1.name === order2.name);
      if(!nameMatch) return;
      return !oldData.some(order2 => order1.name === order2.name && order1.slot === order2.slot);
    });
    
    </script>
    <script src="https://cdn.jsdelivr.net/gh/silentmantra/benchmark/loader.js"></script>
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search