Merge arrays so they contain only recurring values

2019-08-09 10:03发布

问题:

We are upgrading a webshop so the filtering is a little bit different. Now we simply get all product ID's which are related to one or more selected filter values.

//Filter value '8 GB'
$result[] = array(1,6,5,8,9);

//Filter value 'AMD E' (and)OR 'INTEL'
$result[] = array(1,5,8,9,10,500,502,503,600,607,608,...);

The 'AMD E' and 'INTEL' values are from the same filter 'Processor' so we would like these combined as the visitor would like to have all products with an AMD E OR an INTEL processor.

Now we would like to select only the ID's which occur in both array's. We've tried a bunch of methods by now it just doesn't return what we expect in any atempt.

The problem is that the number of key => array pairs in $result is dynamic just like the number of ID's returned by SQL. when the first array in $result is a short list of ID's, array_intersect() will not return all expected results when there are multiple array's in $result.

merge_array() would just combine everything. So the visitor will see ALL products which have 8 GB memory or which contain a AMD E or INTEL processor.

We are looking for a ('8 GB') AND ('ADM E' OR 'INTEL') solution.

Things get complicated when more filters are activated: ('8 GB' OR '12 GB') AND ('ADM E' OR 'INTEL') AND ('HP' OR 'Apple' OR 'Sony')

(Hope I didn't loose you trying to explain the situation and what we are trying to do by now :s)

We've also tried getting stuff done through SQL. As you can read in this question without any luck.

Anyone tackled something like this before?

回答1:

As I understand you want to have a 2-step process:

  1. Find all items that match any criteria in given filter group
  2. Find items that are returned in all used filter groups

For the first step you'll need to find products that match each of selected option. E.g. if user searches for products that have any of options A, B or C, put the results in an array like:

$results = [
 [1,2,3], // products that have option A
 [2,5,7], // products that have option B,
 [2,7,10] // products that have option C
];

You can now get the IDs of all products that have any of those options using

$ids = call_user_func_array('array_merge', $results);

This will give you the sum of arrays.

You have to do that for each filter group that user has selected and you'll get another array of arrays on which now you need to do the intersection operation:

$result = [
  $ids1, // array of IDs that match ANY option from filter group 1
  $ids2  // array of IDs that match ANY option from filter group 2
];

You can get the intersection by calling:

$ids = call_user_func_array('array_intersect', $results);

This will give you IDs of products that match ANY filter option in ALL selected filter groups.

The last thing you'll need is to check if user has selected any filters. If not, do not apply above logic but return all products.

I hope it helps :)