-1

I have a multidimensional array:

var arr1 = 
  [
  [["John"],[50],["Solar"],["Egypt"]],
  [["Joe"],[60],["Wind"],["Ghana"]],
  [["Alan"],[70],["Coal"],["Nigeria"]]
  ]

And another array of filter values:

var arr2 = ["Solar","Wind"]

I want to filter arr1 using values from arr2. So the result should be an array:

var results = 
  [
  [["John"],[50],["Solar"],["Egypt"]],
  [["Joe"],[60],["Wind"],["Ghana"]]
  ]

How can I use .filter() to achieve this? I tried this already but didn't work:

var filtered = var filtered = arr1.filter(function(e) {
  return e[2] == arr2
}
);
Diego
  • 9,261
  • 2
  • 19
  • 33
Ajay Ubhi
  • 329
  • 2
  • 4
  • 12
  • https://stackoverflow.com/a/27448016/1101930 – Jayr Nov 25 '19 at 15:08
  • Does this answer your question? [How to filter an array from all elements of another array](https://stackoverflow.com/questions/34901593/how-to-filter-an-array-from-all-elements-of-another-array) – Dexygen Nov 25 '19 at 21:00

5 Answers5

3

Basically, that's not the way you check if a value exists in an array. Within the context of Google Apps Script, you should use indexOf() (see here for which array methods are supported).

When you compare e[2] == arr2, you're actually checking if ["Solar"] == ["Solar","Wind"]. Clearly, it's not the same. So you need to check if e[2][0], which is just "Solar", exists in the filter array. Using arr2.indexOf(e[2][0]) will return the index of where "Solar" exists in the array; if the value doesn't exist, it will return -1. So all you need to do is check for that -1.

If you can assume that the filter values will always be in the third position, then you can use this fairly simple implementation.

var arr1 = [
  [["John"],[50],["Solar"],["Egypt"]],
  [["Joe"],[60],["Wind"],["Ghana"]],
  [["Alan"],[70],["Coal"],["Nigeria"]]
];
var arr2 = ["Solar","Wind"];
var result = arr1.filter(function(e) {
  return arr2.indexOf(e[2][0]) != -1;
});
Logger.log(result);

Otherwise, you need to check all of the elements of the array. This approach assumes that all of the values are wrapped in their own array, so it extracts them into a single array using map(). You can then use some() to check against all of the filter values.

var arr1 = [
  [["John"],[50],["Solar"],["Egypt"]],
  [["Joe"],[60],["Wind"],["Ghana"]],
  [["Alan"],[70],["Coal"],["Nigeria"]]
];
var arr2 = ["Solar","Wind"];  
var result = arr1.filter(function(e) {
  var joined = e.map(function(element) { return element[0] });
  return arr2.some(function(filterVal) { return joined.indexOf(filterVal) != -1});
});
Logger.log(result);
Diego
  • 9,261
  • 2
  • 19
  • 33
2

filter on the first array. In the callback for each nested array, flatten it and check to see if if some of the elements from the second array are included in it.

Edit: Updated answer as App Scripts doesn't support ES6.

const arr1 = [
  [["John"],[50],["Solar"], ["Egypt"]],
  [["Joe"],[60],["Wind"],["Ghana"]],
  [["Alan"],[70],["Coal"],["Nigeria"]]
];

const arr2 = ["Solar", "Wind"];

function flatten(arr) {
  return arr.reduce(function (acc, val) {
    return acc.concat(val);
  }, []);
}

const out = arr1.filter(function (arr) {
  return arr2.some(function (el) {
    return flatten(arr).indexOf(el) > -1;
  });
});

console.log(out);
Andy
  • 61,948
  • 13
  • 68
  • 95
0

var arr1 = [
  [
    ["John"],
    [50],
    ["Solar"],
    ["Egypt"]
  ],
  [
    ["Joe"],
    [60],
    ["Wind"],
    ["Ghana"]
  ],
  [
    ["Alan"],
    [70],
    ["Coal"],
    ["Nigeria"]
  ]
];
var arr2 = ["Solar", "Wind"];
var filtered = arr1.filter(a1 => arr2.some(a2 => a2 === a1[2][0]));

console.log(filtered);
junvar
  • 11,151
  • 2
  • 30
  • 46
0

Not sure why your data is structured the way it is, but here is a way you could go about it:

var arr1 = 
  [
  [["John"],[50],["Solar"],["Egypt"]],
  [["Joe"],[60],["Wind"],["Ghana"]],
  [["Alan"],[70],["Coal"],["Nigeria"]]
  ]
  
 var arr2 = ["Solar", "Wind"]
 
 console.log(arr1.filter(item => item.flatMap(d => d).some(s => arr2.includes(s))))
thedude
  • 9,388
  • 1
  • 29
  • 30
0

Here's a solution that doesn't assume the order of your first array's elements. Though, it does assume each sub element (i.e. ["Solar"]) only contains one element.

var arr1 = 
  [
  [["John"],[50],["Solar"],["Egypt"]],
  [["Joe"],[60],["Wind"],["Ghana"]],
  [["Alan"],[70],["Coal"],["Nigeria"]]
  ]


var arr2 = ["Solar","Wind"]

let result = arr1.filter(el1 => {
  return arr2.some(el2 => el1.find(x => x[0] === el2))
})

console.log(result)
Neil
  • 2,004
  • 3
  • 23
  • 48