0

In apps script I have the following:

function diff(A, B) {
  return A.filter(function (a) {
    return B.indexOf(a) == -1;
  });
}

When I run:

function testArray(){

  ta = ['a','b','c','d']
  ts = ['a','b','c']

  o =diff(ta,ts)

  Logger.log(o);


}

I get: ['d'] - The correct answer , now I'm trying to apply filter to a 2d array of values - a google sheet.

I tried :

  var ss = SpreadsheetApp.getActiveSpreadsheet();
  var target_sheet_range =   ss.getSheets()[1].getDataRange();
  var target_sheet_values =   target_sheet_range.getValues();
        Logger.log('target_sheet_values');
          Logger.log(target_sheet_values);
  var range = ss.getSheets()[0].getDataRange();
  var values = range.getValues();


          Logger.log('values');
          Logger.log(values);


    var diff_values = diff(values, target_sheet_values)

but this is not taking account the 2d nature of the arrays. You can see it at google spreadsheet https://docs.google.com/spreadsheets/d/1fFr9Sz2EAiMYoybg-evV33n_BZjF-1QNnnKqiqSXQ_g/edit?usp=sharing

output:

[18-06-23 14:45:22:129 EDT] target_sheet_values
[18-06-23 14:45:22:130 EDT] [[a, a, a, a, a], [z, x, c, v, b], [m, n, b, v, c]]
[18-06-23 14:45:22:457 EDT] values
[18-06-23 14:45:22:458 EDT] [[a, a, a, a, a], [z, x, c, v, b], [m, n, b, v, c], [a, s, d, f, g], [q, w, e, r, t]]
[18-06-23 14:45:22:459 EDT] hhhhhh
[18-06-23 14:45:22:459 EDT] [[a, a, a, a, a], [z, x, c, v, b], [m, n, b, v, c], [a, s, d, f, g], [q, w, e, r, t]]

How do I modify the filter function 2 filter a 2d array

Rubén
  • 34,714
  • 9
  • 70
  • 166
user1592380
  • 34,265
  • 92
  • 284
  • 515
  • 1
    Related: [Equivalent of “=Query(ImportRange(” in Google Apps Script?](https://stackoverflow.com/q/26544982/1595451) – Rubén Jun 23 '18 at 19:08
  • Possible duplicate of [How to filter an array of arrays](https://stackoverflow.com/questions/40849369/how-to-filter-an-array-of-arrays) – Rubén Feb 18 '19 at 18:18

2 Answers2

2

You problem is related to the fact that in javascript [1, 2, 3] != [1, 2, 3]. Arrays and object comparisons are not done by the values. This also applies to indexOf(). For example:

var a = [[1, 2, 3], [4, 5, 6]]
var b = [4, 5, 6]

console.log(a.indexOf(b)) // returns -1

To fix this you need to write a function that defines equality the way you want. For example:

// arrays with the same values in the same order will be considered equal
function array_equals(a, b){
    return a.length === b.length && a.every((item,idx) => item === b[idx])
}

console.log(array_equals([1, 2, 3], [1, 2, 3]))
console.log(array_equals([1, 2, 3], [1, 2, 4]))

With that in hand you can now filter with something like:

var a = [[1,2,3], [4, 5, 6], [7, 8, 9]]
var b = [[1, 2, 3], [4, 5, 6]]


function array_equals(a, b){
    return a.length === b.length && a.every((item,idx) => item === b[idx])
}

function diff(A, B) {
    return A.filter(test => {
      return B.findIndex(item => array_equals(item,test)) == -1;
    });
  }
console.log(diff(a,b))
Mark
  • 90,562
  • 7
  • 108
  • 148
  • 1
    Google Apps script doesn't support let. Related [Declaring variables on Google sheet script editor using let](https://stackoverflow.com/q/48654622/1595451) – Rubén Jun 23 '18 at 19:09
  • 1
    Thanks @Rubén, didn't know that. Edited. – Mark Jun 23 '18 at 19:10
  • 1
    Arrow functions aren't supported either (I just noticed that you used them too). – Rubén Jun 23 '18 at 20:00
  • 1
    Unfortunately, ``findIndex`` cannot be used at Google Apps Script yet. Because it was added from ECMAScript 2015 (ES6). https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/findIndex – Tanaike Jun 24 '18 at 00:08
1

You want to retrieve [[a, s, d, f, g], [q, w, e, r, t]] from [[a, a, a, a, a], [z, x, c, v, b], [m, n, b, v, c], [a, s, d, f, g], [q, w, e, r, t]] and [[a, a, a, a, a], [z, x, c, v, b], [m, n, b, v, c]]. If my understanding is correct, how about this sample script? I think that there are several answers for your situation. Please think of this as one of them.

Sample script :

var res = values.filter(
   function(e) {
      return target_sheet_values.filter(
         function(f) {
            return e.toString() == f.toString()
         }).length == 0
   });

var target_sheet_values = [
   ["a","a","a","a","a"],
   ["z","x","c","v","b"],
   ["m","n","b","v","c"]
];
var values = [
   ["a","a","a","a","a"],
   ["z","x","c","v","b"],
   ["m","n","b","v","c"],
   ["a","s","d","f","g"],
   ["q","w","e","r","t"]
];

var res = values.filter(
   function(e) {
      return target_sheet_values.filter(
         function(f) {
            return e.toString() == f.toString()
         }).length == 0
   });
console.log(res);

Result

[["a","s","d","f","g"],["q","w","e","r","t"]]

Note :

  • values and target_sheet_values are from your script.
  • When you use this, for your script, please use this instead of var diff_values = diff(values, target_sheet_values).

If I misunderstand what you want, please tell me. I would like to modify it.

Owen Blacker
  • 4,117
  • 2
  • 33
  • 70
Tanaike
  • 181,128
  • 11
  • 97
  • 165