skip to Main Content

I want to return the first item in an array of objects that does not have a matching id to any object in a separate array. For example,

arrary1 = [
 { name: "object1", id: 1, coordinates: undefined}
 { name: "object2", id: 2, coordinates: undefined}
 { name: "object3", id: 3, coordinates: undefined}
 { name: "object4", id: 4, coordinates: undefined}
 { name: "object5", id: 5, coordinates: undefined}
]

and 

array2 = [
 { name: "object1", id: 1, coordinates: [3,2]}
 { name: "object2", id: 2, coordinates: [1,1]}
 { name: "object3", id: 3, coordinates: [3,6]}
]

Should return:

{ name: "object4", id: 4, coordinates: undefined}

I want to return the first item in array1 that does not have the same id as any of the objects in array2. (I cannot just compare the objects as a whole because there might be other differing key value pairs. I only care about the id.)

I am trying:

    const firstUniqueItem = find(array1, function (object1) {
      return !array2.some((object2) => {object2.id === object1.id})
    });

This will work when array2 is empty, but still just returns the first item of array1 when array2 has has an object with a matching id.

What do I need to fix? Is there a better way to accomplish this?

2

Answers


  1. One way is to filter array1 and remove any occurrence of array2, then take the first item.

    array1.filter(a => !array2.find(b => b.id==a.id))[0] || false
    

    The || false at the end gives you a boolean just in case there isn’t a match. Otherwise you’d get undefined

    let array1 = [
     { name: "object1", id: 1, coordinates: undefined},
     { name: "object2", id: 2, coordinates: undefined},
     { name: "object3", id: 3, coordinates: undefined},
     { name: "object4", id: 4, coordinates: undefined},
     { name: "object5", id: 5, coordinates: undefined}
    ]
    
    let array2 = [
     { name: "object1", id: 1, coordinates: [3,2]},
     { name: "object2", id: 2, coordinates: [1,1]},
     { name: "object3", id: 3, coordinates: [3,6]}
    ]
    
    let answer = array1.filter(a => !array2.find(b => b.id==a.id))[0] || false;
    console.log(answer)
    Login or Signup to reply.
  2. As @carcigenicate mentions in his comment, the function you pass to some() does not return the value.

    There are a few other weird things about your code, creating an actual snippet that ran would help. For instance your first array is declared as arrary1 but used as array. Also you use a find(array1) function that doesn’t exist in javascript, I assume you mean array1.find().

    array1 = [
     { name: "object1", id: 1, coordinates: undefined},
     { name: "object2", id: 2, coordinates: undefined},
     { name: "object3", id: 3, coordinates: undefined},
     { name: "object4", id: 4, coordinates: undefined},
     { name: "object5", id: 5, coordinates: undefined}
    ]
    
    array2 = [
     { name: "object1", id: 1, coordinates: [3,2]},
     { name: "object2", id: 2, coordinates: [1,1]},
     { name: "object3", id: 3, coordinates: [3,6]}
    ]
    
    //Should return:
    //{ name: "object4", id: 4, coordinates: undefined}
    
    const firstUniqueItem = array1.find(function (object1) {
      return !array2.some((object2) => {
        return object2.id === object1.id
      })
    });
        
    console.log(`firstUniqueItem: ${JSON.stringify(firstUniqueItem)}`)

    Of course this is horribly inefficient. If you have 1000 elements in array2 and 1001 elements in array1, you could be doing a million comparisons to find the one element that isn’t in array2. You can make this faster by first creating an object with property names that are the ids in array2 with values ‘true’ (or anything truthy).

    const mappedIds = array2.reduce((prev, curr) => {
      prev[curr.id] = true;
      return prev;
    }, {});
    
    const firstUniqueItem = array1.find(x => !mappedIds[x.id]);
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search