How to Filter a Two Dimensional Array by Value

How to filter a two dimensional array by value

Use PHP's array_filter function with a callback.

$new = array_filter($arr, function ($var) {
return ($var['name'] == 'CarEnquiry');
});

Edit: If it needs to be interchangeable, you can modify the code slightly:

$filterBy = 'CarEnquiry'; // or Finance etc.

$new = array_filter($arr, function ($var) use ($filterBy) {
return ($var['name'] == $filterBy);
});

Filter multidimensional array by equal values in sub array (PHP)

You can create two arrays with the help of filtering by necessary values. You can use array_filter function to it, but you should find a necessary value in each element that passed to array_filter function.

For example, finding 'req' value

$req = array_filter($my_array, function ($v) {
return in_array('req', $v);
});

For example, finding 'opt' value

$opt = array_filter($my_array, function ($v) {
return in_array('opt', $v);
});

I used in_array function to finding values because each element is an array that has different quantity of elements

How to filter multidimensional array based on another multidimensional array of exclusions?

Breaking your exclusion array into separate variables is not advisable because this will make your code harder / more tedious to maintain when you want to modify the exclusion list.

Iterate your products array just one time.  Inside that loop, loop the attributes in each product having keys which match the first level keys in the exclusion array. This is what array_intersect_key() does best and this prevents performing an unnecessary comparison on the Product ID elements.  As soon as you find a disqualifying condition to be satisfied, stop the inner loop for best efficiency.

Code #1 (Demo) *my recommendation

$result = [];
foreach ($products as $product) {
foreach (array_intersect_key($product, $exclusions) as $key => $value) {
if (in_array($value, $exclusions[$key])) {
continue 2;
}
}
$result[] = $product;
}
var_export($result);

Code #2: (Demo)

foreach ($products as $index => $product) {
foreach (array_intersect_key($product, $exclusions) as $key => $value) {
if (in_array($value, $exclusions[$key])) {
unset($products[$index]);
break;
}
}
}
var_export(array_values($products));

Code #3: (Demo)

var_export(
array_values(
array_filter(
$products,
function($product) use ($exclusions) {
return !array_filter(
array_intersect_key($product, $exclusions),
function($value, $key) use ($exclusions) {
return in_array($value, $exclusions[$key]);
},
ARRAY_FILTER_USE_BOTH
);
}
)
)
);

Code #4: (Demo)

var_export(
array_values(
array_filter(
$products,
fn($product) => !array_filter(
array_intersect_key($product, $exclusions),
fn($value, $key) => in_array($value, $exclusions[$key]),
ARRAY_FILTER_USE_BOTH
)
)
)
);

Code #1 uses continue 2; to stop the halt the inner loop, avoid storing the current product in the output array, then return to the outer loop to carry on processing the next product.

Code #2 is directly modifying the $products array.  By unsetting products, the array may cease to be an indexed array (the keys may have gaps between integers). If desirable, call array_values() after the loop to re-index the output.

Code #3 is using a functional style.  It is common for language constructs (e.g. foreach()) to outperform functional iterators, so I will assume this snippet (and Code #4) will be slightly slower than the first two.  Furthermore, array_filter() doesn't enjoy the early return that the foreach loops have with break and continue.  In other words, Code #3 & #4 will continue checking against the exclusion array even if a disqualifying condition has already been satisfied for a given product. And if that wasn't enough, I simply find the syntax too convoluted.

Code #4 is the same as Code #3, but is using the slightly shorter "arrow function" syntax which is available from PHP7.4 and up.  This affords the omission of use() and some other characters, but I still find the snippet less intuitive/readable compared to Code #1 & #2.

How to use filter() on a multidimensional array using values from another array?

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);

Tips on filtering two dimensional array

This should do the trick:

var result = structure.variants
// Throw away variants without prices
.Where(variant => variant.prices != null)
// For each variant, select all needle prices (.toString) and flatten it into 1D array
.SelectMany(variant => variant.prices.Select(price => price.needle.ToString()))
// And choose only unique prices
.Distinct();

For structure like this:

var structure = new Item(
new Variant(new Price(200), new Price(100), new Price(800)),
new Variant(new Price(100), new Price(800), new Price(12))
);

is output [ 200, 100, 800, 12 ].

How does it work?

.SelectMany basically takes array-inside-array and turns it into normal array. [ [1, 2], [3, 4] ] => [ 1, 2, 3, 4 ], and .Distinct throws away duplicate values.

The code I came up with is almost exactly the same as yours. It looks like you are doing .Distinct on .Select, not on .SelectMany. What's the difference? .Select selects one value (in this case) - it's pointless to call Distinct on it, which drop duplicates. .SelectMany selects many values - so if you want to call Distinct somewhere, it should be on result of SelectMany.

Filtering two-dimensional arrays in Javascript

Iterate over the items, use Array#filter function to filter those inner arrays which does not have the given value in the given position.