1

let's assume that we have two arrays like these:

let s1 =  ["A", "B", "C", "D", "B"]  // Note: "B" has been occurred 2 times
let s2 =  ["A", "B", "C", "D", "B", "A", "X", "Y"] // // Note: "B" has been occurred 2 times just like s1 but we have another occurrence for "A" 

I want to create a new array (let s3) based on these two arrays with this rule that we'll remove the element(s) with occurrences more than the same element's occurrence in array s1

so the s3 array would be like this:

let s3 =  ["A", "B", "C", "D", "B", "X", "Y"] // we just removed "A" cause it occurred more than "A" occurances in s1

Note that we want anything else ("X", "Y"). we just want to handle the extra occurrences.

so far I can find the index of repeated occurrences like this but I can't find a way to compare each occurrence to see if it is an extra one or not (complicated):

    let s1 =  ["A", "B", "C", "D", "B"]  
    let s2 =  ["A", "B", "C", "D", "B", "A", "X", "Y"]  

    var s3 = [];  
     
    for (let i = 0; i < s2.length; i++) {
    for (let j = 0; j < s1.length; j++) {
     if (s2[i] === s1[j]) {
         s3.push(i);
         break;
  }
}        
  }     
    console.log(s3)

My English is poor and I don't know if I could explain the issue or not!

Note: I can simply use s3 = [...new Set(s2)] to remove repeated elements but I want something else.

Sara Ree
  • 3,417
  • 12
  • 48
  • Thanks for the comment Michael but it's different... I can simply use `s2 = [...new Set(s2)]` to remove repeated elements but I want something else... – Sara Ree Aug 05 '19 at 16:51
  • Sorry, reread the question. You want the [union](https://stackoverflow.com/questions/3629817/getting-a-union-of-two-arrays-in-javascript) of the arrays. – Michael Bianconi Aug 05 '19 at 16:53
  • Is this the answer you're looking for? https://stackoverflow.com/questions/9229645/remove-duplicate-values-from-js-array – maxpelic Aug 05 '19 at 16:58
  • Thanks ... I'll try those ... – Sara Ree Aug 05 '19 at 17:03

3 Answers3

3

Since you want to keep everything originally in s1 but only add items from s2 if they aren't already in you can initially set s3 to s1. Then loop over s2 and if s1 does not have the value then push it into s3.

const s1 = ["A", "B", "C", "D", "B"];
const s2 = ["A", "B", "C", "D", "B", "A", "X", "Y"];

const s3 = [...s1];

s2.forEach(d => {
  if (!s1.includes(d)) s3.push(d);
});

console.log(s3);
vivalldi
  • 511
  • 2
  • 14
2

You could count the values of the first set and return the values for a given count or if not known then all items.

var s1 =  ["A", "B", "C", "D", "B"],
    s2 =  ["A", "B", "C", "D", "B", "A", "X", "Y"],
    count = s1.reduce((m, v) => m.set(v, (m.get(v) || 0) + 1), new Map),
    s3 = s2.filter(v => count.get(v) ? count.set(v, count.get(v) - 1) : !count.has(v));

console.log(...s3);
Nina Scholz
  • 376,160
  • 25
  • 347
  • 392
2

You can use Map and filter

  • First Map the array1 to [key, value] format
  • Iterate over second array, if it's found in Map and value is grater than zero return true else return false,
  • If it is not found return true

let s1 =  ["A", "B", "C", "D", "B"]  
let s2 =  ["A", "B", "C", "D", "B", "A", "X", "Y"]  

let map = new Map()

s1.forEach(v=>{
  if(map.has(v)){
    map.set(v,map.get(v)+1)
  } else{
    map.set(v,1)
  }
})

let final = s2.filter(val=>{
  if(map.has(val)){
    if(map.get(val)){
      map.set(val, map.get(val)-1)
      return true
    } 
    return false
  }
  return true
})

console.log(final)
Code Maniac
  • 37,143
  • 5
  • 39
  • 60