Remove similar elements from an array when they match a value in another array, but only for the number of elements in 2nd array.

I have 2 arrays:

var items = [{quantity: 3, name: "test Item 1", relatedId: "hill123", Id: "111-111"}, 
            {quantity: 1, name: "test Item 2", relatedId: "lane222", Id: "222-222"},
            {quantity: 1, name: "test Item 3", relatedId: "buncha333", Id: "333-333"}
            
            ];
var relatedItems =[{quantity: 1, name: "Related Item 1", Id: "hill123"},
                    {quantity: 1, name: "Related Item 1", Id: "hill123"},
                    {quantity: 1, name: "Related Item 2", Id: "bump222"},
                    {quantity: 1, name: "Related Item 3", Id: "buncha333"}
];

And I need 1 new array with the relatedItems that are not already present and matching, removed.

For example, "test item 1" has 3 quantity, but only 2 related items in the relatedItems list, so I need 1 item in a new array. Plus the "test item2" that does not have a matching related item, but not "test item 3" because it has a related item and the 1 quantiy matches the 1 relatedItem.

so at the end I need an Array that looks like this:

filterList = [{Id: "hill123"}, {Id: "lane222"}]

I have tried so many things, but here is my last few tries, I really thought the top one would work - based on a similar question, but it kept taking too many elements off, leaving only "Single item: lane222" and not the 2 needed.

var items = [{quantity: 3, name: "test Item 1", relatedId: "hill123", Id: "111-111"}, 
            {quantity: 1, name: "test Item 2", relatedId: "lane222", Id: "222-222"},
            {quantity: 1, name: "test Item 3", relatedId: "buncha333", Id: "333-333"}
            
            ];
var relatedItems =[{quantity: 1, name: "Related Item 1", Id: "hill123"},
                    {quantity: 1, name: "Related Item 1", Id: "hill123"},
                    {quantity: 1, name: "Related Item 2", Id: "bump222"},
                    {quantity: 1, name: "Related Item 3", Id: "buncha333"}
];

var singleQuantity = [];
items.forEach(function(item){
  //console.log('item: ' + item.name + " --> " + item.quantity + " --> " + item.relatedId)
  if(item.quantity > 1){
    for(var i=0; i < item.quantity; i++){
      singleQuantity.push(item);
    } 
  }else {
      singleQuantity.push(item);
    }
});

if(singleQuantity){
  singleQuantity.forEach(function(item){
    item.quantity = 1;
  })
}

var relatedIdsOnly = [];
var itemRelatedIdsOnly = [];

singleQuantity.forEach(function(item){
  itemRelatedIdsOnly.push(item.relatedId);
})

relatedItems.forEach(function(item){
  relatedIdsOnly.push(item.Id)
})

for (var i = 0; i< relatedIdsOnly.length; i++) {
    var arrlen = itemRelatedIdsOnly.length;
    for (var j = 0; j<arrlen; j++) {
        if (relatedIdsOnly[i] == itemRelatedIdsOnly[j]) {
            itemRelatedIdsOnly = itemRelatedIdsOnly.slice(0, j).concat(itemRelatedIdsOnly.slice(j+1, arrlen));
        }
    }
    // gives me only 1 item, not 2.  "Single item: lane222" it should have 1 item: hill123 also
}

itemRelatedIdsOnly.forEach(function(item){
  console.log('Single item: ' + item)
});



// for( var i = 0; i < relatedItems.length; i++){
//   var arrlen = singleQuantity.length;
//   console.log(arrlen + " " + relatedItems.length)
//   for (var j = 0; j < arrlen; j++){
//     if (relatedItems[i].Id == singleQuantity[j].relatedId){
//       console.log('match ' + relatedItems[i].Id + " " + singleQuantity[j].relatedId)
//       singleQuantity = singleQuantity.slice(0, j).concat(singleQuantity.slice(j+1, arrlen))
//       // did not remove anything - gave me an error - TypeError: Cannot read properties of undefined (reading 'relatedId')
//       // at <anonymous>:76:49
//       // at mn (<anonymous>:16:5455)
//     }
//   }
// }


// for( var i = 0; i < relatedItems.length; i++){
//   var arrlen = singleQuantity.length;
//   for (var j = 0; j < arrlen; j++){
//     if (relatedItems[i].Id == singleQuantity[j].relatedId){
//       console.log('match ' + relatedItems[i].Id + " " + singleQuantity[j].relatedId)
//       singleQuantity = singleQuantity.slice(0, j).concat(singleQuantity.slice(j+1, arrlen))
//       // gave me an error -
//     }
//   }
// }


// relatedItems.forEach(function(rel){
//   console.log('rel: ' + rel.Id)
//   singleQuantity.forEach(function(item, index, object ){
//     console.log(item.name)
//     if(item.relatedId === rel.Id){
//       object.splice(index, 1)
        
//     }
//   });
// });

// singleQuantity.forEach(function(rel, index, object ){
//   relatedItems.forEach(function(item){
//     if(item.relatedId === rel.Id){
//       object.splice(index, 1) // didnt splice anything        
//     }
//   });
// })



// relatedItems.forEach(function(rel){
//   //console.log('rel: ' + rel.Id)
//   items.forEach(function(item, index, object ){
//     //console.log(item.name)
//     if(item.relatedId === rel.Id && item.quantity > 1){
//       dupsList.push(item);
//     } else if(item.relatedId !== rel.Id && item.quantity === 1){
//       //console.log('not match')
//       filteredList.push(rel.Id);
//     }
//   });
// });


1

There are 1 best solutions below

3
Mister Jojo On BEST ANSWER

Something like that ?

const
  items = 
    [ { quantity: 3, name: 'test Item 1', relatedId: 'hill123',   Id: '111-111' } 
    , { quantity: 1, name: 'test Item 2', relatedId: 'lane222',   Id: '222-222' } 
    , { quantity: 1, name: 'test Item 3', relatedId: 'buncha333', Id: '333-333' } 
    ] 
, relatedItems = 
    [ { quantity: 1, name: 'Related Item 1', Id: 'hill123'   } 
    , { quantity: 1, name: 'Related Item 1', Id: 'hill123'   } 
    , { quantity: 1, name: 'Related Item 2', Id: 'bump222'   } 
    , { quantity: 1, name: 'Related Item 3', Id: 'buncha333' } 
    ]
, result = []
  ;

for (let {quantity:Qte, relatedId:Id} of items) 
  {
  let Qsum = relatedItems.reduce((sum,{quantity,Id:rId}) => sum += Id===rId ? quantity : 0, 0);
  if (Qte > Qsum) result.push({Id});
  }

document.write( JSON.stringify(result) );

[EDIT]
As pilchard points out in his comment, this code can be optimized ( should be in case of large arrays). Here is my optimization option:

items = 
    [ { quantity: 3, name: 'test Item 1', relatedId: 'hill123',   Id: '111-111' } 
    , { quantity: 1, name: 'test Item 2', relatedId: 'lane222',   Id: '222-222' } 
    , { quantity: 1, name: 'test Item 3', relatedId: 'buncha333', Id: '333-333' } 
    ] 
, relatedItems = 
    [ { quantity: 1, name: 'Related Item 1', Id: 'hill123'   } 
    , { quantity: 1, name: 'Related Item 1', Id: 'hill123'   } 
    , { quantity: 1, name: 'Related Item 2', Id: 'bump222'   } 
    , { quantity: 1, name: 'Related Item 3', Id: 'buncha333' } 
    ]
  // prepare all sums for optimization
, relatedItemsSums = relatedItems.reduce( (resume,{quantity,Id}) => 
    {
    resume[Id] ??= 0; 
    resume[Id] += quantity; 
    return resume
    } ,{})
, result = []
  ;

for (let {quantity:Qte, relatedId:Id} of items) 
  {
  let Qsum = relatedItemsSums[Id] ?? 0;
  if (Qte > Qsum) result.push({Id});
  }

console.log( result );