2

I have two arrays in jQuery as below.

var arr1 = [{A: "t1"},{A: "t3"}];

var arr2 = [{A: "t1",B:""},{A: "t2",B:""},{A: "t3",B:""},{A: "t4",B:""},{A: "t5",B:""},{A: "t6",B:""}];

var arr3 = []; //Only for output

Now, the output in arr3 should be:

  • all the values from arr2
  • the 'B' key should be Yes if 'A' key exists in arr1
  • the 'B' key should be No if 'A' key doesn't exist in arr1

So, the output I want in arr3 should be:

arr3 = [{A: "t1",B:"Yes"},{A: "t2",B:"No"},{A: "t3",B:"Yes"},{A: "t4",B:"No"},{A: "t5",B:"No"},{A: "t6",B:"No"}];

This is what I have tried so far

var arr1 = [{A: "t1"},{A: "t3"}];
var arr2 = [{A: "t1",B:""},{A: "t2",B:""},{A: "t3",B:""},{A: "t4",B:""},{A: "t5",B:""},{A: "t6",B:""}];
var arr3 = []; //Only for output

arr1.forEach(function(x) {
  arr2.forEach(function(y) {
    if (x.A == y.A) {
      arr3.push({
        A: x.A,
        B: "Yes"
      });
    } else {
      arr3.push({
        A: x.A,
        B: "No"
      });
    }
  });
});

console.log(arr3);
//Output
0: {A: "t1", B: "Yes"}
1: {A: "t1", B: "No"}
2: {A: "t1", B: "No"}
3: {A: "t1", B: "No"}
4: {A: "t1", B: "No"}
5: {A: "t1", B: "No"}
6: {A: "t3", B: "No"}
7: {A: "t3", B: "No"}
8: {A: "t3", B: "Yes"}
9: {A: "t3", B: "No"}
10: {A: "t3", B: "No"}
11: {A: "t3", B: "No"}

Issue here is that it repeats for each item in arr1, and count gets doubled. I know it should break somewhere between if and else, so that it does not repeat.

I have tried checking below links too, but couldn't get much help.

filter array of objects based on separate object keys, values

js - How to change one key's value based on another key's value in array of objects

Object comparison based on keys

compare array of objects

Thanks in advance.

mplungjan
  • 169,008
  • 28
  • 173
  • 236
foodiepanda
  • 128
  • 1
  • 14

2 Answers2

2

Use map and find if the arrays are not huge.

Saves a reduce and push

var arr1 = [{ A: "t1" }, { A: "t3" }];
var arr2 = [{ A: "t1", B: ""}, { A: "t2", B: "" }, { A: "t3", B: "" }, { A: "t4", B: "" }, { A: "t5", B: "" }, { A: "t6", B: "" }];
var arr3 = arr2.map(
  item2 => ({
    A: item2.A,
    B: arr1.find(item1 => item1.A === item2.A) ? 'Yes' : 'No'
  }));

console.log(arr3);
mplungjan
  • 169,008
  • 28
  • 173
  • 236
1

You can make an array of the A values in arr1 using Array.reduce(), then use Array.includes to check if each of the A values in arr2 is present in that array, using that to decide whether to set B to Yes or No:

var arr1 = [{ A: "t1" }, { A: "t3" }];
var arr2 = [{ A: "t1", B: ""}, { A: "t2", B: "" }, { A: "t3", B: "" }, { A: "t4", B: "" }, { A: "t5", B: "" }, { A: "t6", B: "" }];
var arr3 = []; //Only for output

var arr1values = arr1.reduce((c, v) => c.concat([v.A]), []);

arr2.forEach(function(y) {
  arr3.push({
    A: y.A,
    B: arr1values.includes(y.A) ? 'Yes' : 'No'
  });
});

console.log(arr3);
Nick
  • 138,499
  • 22
  • 57
  • 95
  • Great, that worked like a charm. Array.reduce() and Array.includes is something new that I learned today. Much appreciated. – foodiepanda Apr 08 '20 at 06:57
  • Would be interesting to compare our two answer in some benchmark test for 5000 items – mplungjan Apr 08 '20 at 07:05
  • @mplungjan indeed. I guess it will largely come down to whether `includes` is enough faster than `find` to make up for the `reduce`. – Nick Apr 08 '20 at 07:25