1

I have two sets of numeric elements stored as 2D array. The values were grabbed from a column using .getValues(). One is a full list the other is a partial list. I want a function that returns full list minus partial list.

  • The partialListArr may contain duplicates. The fullListArr does not.
  • I need the output to also be a 2D list as they will be used in .setValues().
  • Values are all numbers.

Here is what I've tried.

function myFunction() {
  var ss = SpreadsheetApp.getActive();
  var partialListArr = ss.getSheetByName('sheet 2').getRange(1,1,357,1).getValues();
  var fullListArr = ss.getSheetByName('sheet 1').getRange(1,1,942,1).getValues();

  var arr = fullListArr.filter(function(item){
    return partialListArr.indexOf(item.id) === -1;
  }); 

  Logger.log(arr.length)
  Logger.log(arr)
}

This returns the full list.

I also tried this:

function myFunction2(){
  var ss = SpreadsheetApp.getActive();
  var partialListArr = ss.getSheetByName('sheet 2').getRange(1,1,357,1).getValues();
  var fullListArr = ss.getSheetByName('sheet 1').getRange(1,1,942,1).getValues();

  var arr = fullListArr.map(function(e){return e[0];})
    .filter(function(e,i,a){return (a.indexOf(e)==i && partialListArr.indexOf(e) ==-1); })  

  Logger.log(arr.length)
  Logger.log(arr)
} 

It will return only part of the results. If fullListArr has 943 and partialListArr has 288 unique values, I should have 655 values in arr but I'm getting 895 and it is not returning it as a 2D array.

Here is a sheet with a data set and both of these included.

Attempts: First I need to flatten if using the first function.

  var ss = SpreadsheetApp.getActive();
  var partialListArr = ss.getSheetByName('sheet 2').getRange(1,1,357,1).getValues();
  var fullListArr = ss.getSheetByName('sheet 1').getRange(1,1,942,1).getValues();

  var flatPartialListArr = [].concat.apply([], partialListArr);
  var flatFullListArr = [].concat.apply([], fullListArr);

  var arr = flatFullListArr.filter(function(item){
    return flatPartialListArr.indexOf(item) === -1;
  }); 

  Logger.log(arr.length)
  Logger.log(arr)

That gave me the correct number for arr. Next step is to make it a 2d array again for me to plug it in .setValues. Here is the function with the full solution.

function myFunction() {
  var ss = SpreadsheetApp.getActive();
  var partialListArr = ss.getSheetByName('sheet 2').getRange(1,1,357,1).getValues();
  var fullListArr = ss.getSheetByName('sheet 1').getRange(1,1,942,1).getValues();

  var flatPartialListArr = [].concat.apply([], partialListArr);
  var flatFullListArr = [].concat.apply([], fullListArr);

  var flatArr = flatFullListArr.filter(function(item){
    return flatPartialListArr.indexOf(item) === -1;
  }); 

  //Convert to 2D again for input into .setValues
  var newArr = [];
  while(flatArr.length) newArr.push(flatArr.splice(0,1));

  Logger.log(newArr.length)
  Logger.log(newArr)

  return newArr;
}

Thank you Akrion!

TheMaster
  • 45,448
  • 6
  • 62
  • 85
DanCue
  • 619
  • 1
  • 8
  • 17
  • 1
    can you provide what is the structure of `item`? It seems your filtering is ok but maybe the `id` field is not the one you should be filtering on? – Akrion Aug 10 '18 at 18:36
  • @Akrion I've linked a sheet so you can take a look at the data. – DanCue Aug 10 '18 at 18:49
  • 1
    the sheet gives me the raw sheet data but not the actual objects that contain it. It seems `ss.getSheetByName('sheet 2').getRange(1,1,357,1).getValues()` for example does not return values but objects no? If no then why do you have `item.id`? – Akrion Aug 10 '18 at 18:53
  • @Akrion The logs show [[60],[10004],[5678]....] – DanCue Aug 10 '18 at 18:56
  • 1
    Exactly ... you have array of arrays :) which means you need to flatten this first before you itterate – Akrion Aug 10 '18 at 18:57
  • @Akrion Does the second function do that? And if I flatten, I then have to convert to 2D? – DanCue Aug 10 '18 at 18:59
  • @Akrion. Ok. I think I got it. I'll update my question. – DanCue Aug 10 '18 at 19:09

1 Answers1

1

It seems you have something like this:

var full = [[1],[2],[3],[4],[5]]
var partial = [[3],[4]]

var result = full.filter(x => !partial.find(p => p[0] === x[0]))
console.log(result)

This will filter the way you want. Simply put your filter does not work since you did not take into account the result returned, which is [[], [], []] or array of arrays.

So in your context try this:

var arr = fullListArr.filter(item => !partialListArr.find(p ==> p[0] === item[0]);
Akrion
  • 18,117
  • 1
  • 34
  • 54
  • 2
    Arrow and `find` are not available in Apps Script – tehhowch Aug 10 '18 at 19:21
  • I have tried to use a similar solution to this but I get a syntax error. I'm assuming it's because google apps script does not take `=>`. I could be wrong. – DanCue Aug 10 '18 at 19:21
  • @tehhowch You beat me to it. Thanks for confirming. – DanCue Aug 10 '18 at 19:22
  • 1
    @DanCue well it does not matter that much you ware able to solve it once you figured out that the array of arrays was the issue right? – Akrion Aug 10 '18 at 19:24
  • @tehhowch thanks I did not test there but in the console so that was a good correction. – Akrion Aug 10 '18 at 19:25
  • @Akrion That is correct. Do you want to post my solution so you can get the credit since it was thanks to you? – DanCue Aug 10 '18 at 19:30
  • No that is fine. You can just accept the answer and add a note that you took that approach and got the solution. Either way is fine it is up to you. Glad you solved the issue. Rest is just numbers :) – Akrion Aug 10 '18 at 19:31