I have 3 different multidimensional arrays:
// INPUT DATA WITH HOUSE DESCRIPTION. STRUCTURE: ID, OPTION DESCRIPTION
$input_house_data = array (
array("AAA","Chimney with red bricks"),
array("BBB","Two wide windows in the main floor"),
array("CCC","Roof tiles renewed in 2015")
);
// CATALOGUE WITH ALL HOUSE EQUIPMENT OPTIONS. STRUCTURE: ID, OPTION NAME
$ct_all_house_options = array (
array("0001","Chimney"),
array("0002","Garden"),
array("0003","Roof tiles"),
array("0004","Windows"),
array("0005","Garage")
);
// SEARCH STRINGS AS REGULAR EXPRESSIONS. STRUCTURE: ID, EQUIPMENT OPTION NAME, REGULAR EXPRESSION TO SEARCH
$ct_house_options = array (
array("0001","Chimney","/^Chimney with./"),
array("0003","Roof tiles","/^Roof tiles./"),
array("0004","Windows","/.windows./"),
array("0004","Windows","/.wide windows./")
);
I would like to search within $input_house_data by use of the regular expressions from the array $ct_house_options in order to indicate which equipment has a house. The result should be the whole list with all possible options and status "available" or "not available":
0001 - Chimney - available
0002 - Garden - not available
0003 - Roof tiles - available
0004 - Windows - available
0005 - Garage - not available
I tried to realize it as following:
$arrlength_input_house_data = count($input_house_data);
$arrlength_ct_all_house_options = count($ct_all_house_options);
$arrlength_ct_house_options = count($ct_house_options);
For loop with preg_match function. All results are written into array $matches (including dublicates):
for ($row1 = 0; $row1 < $arrlength_input_house_data; $row1 ) {
for ($row2 = 0; $row2 < $arrlength_ct_house_options; $row2 ) {
if (preg_match($ct_house_options[$row2][2], $input_house_data[$row1][1]) === 1) {
$matches[] = $ct_house_options [$row2][0];
}
}
}
Deleting of dublicates:
$unique = array_unique($matches);
print_r($unique);
So now I have got the unique results:
Array ( [0] => 0001 [1] => 0004 [3] => 0003 )
The next step should be merge of the array $ct_all_house_options and unique results from $unique. Unfortunatelly I cannot get it zealized. Do you have any idea how to get it? Maybe is any more simple way to realize it?
CodePudding user response:
Loop through the array with all options. Check if the ID is in your $unique
list, then it's available.
foreach ($ct_all_house_options as [$id, $name]) {
if (in_array($id, $unique)) {
echo "$id - $name - available<br>";
} else {
echo "$id - $name - not available<br>";
}
}
CodePudding user response:
If performance is very important, you can prepare associative arrays to access the data faster. Here's a solution for the entire problem:
$optionsById = [];
foreach ($ct_house_options as $option) {
$optionsById[$option[0]] = $option;
}
$availabilityById = [];
foreach ($ct_all_house_options as $option) {
$id = $option[0];
$availabilityById[$id] = false;
foreach ($input_house_data as $data) {
$option = $optionsById[$id] ?? null;
if (!$option) {
continue;
}
if (preg_match($option[2], $data['1'])) {
$availabilityById[$id] = true;
break;
}
}
}
foreach ($ct_all_house_options as $option) {
$availabilityString = $availabilityById[$option[0]]
? 'available'
: 'not available';
echo "$option[0] - $option[1] - $availabilityString\n";
}
Performance:
- Execution time:
- min: 0.00000476837158203s
- max: 0.00047588348388672s
- avg: 0.0000226473808289s
- Memory usage: 396KB
It's possible to do it with less code, though, if the foreach
loop is changed:
$available = [];
foreach ($input_house_data as $data) {
foreach ($ct_house_options as $option) {
if (preg_match($option[2], $data['1'])) {
$available[$option[0]] = true;
}
}
}
foreach($ct_all_house_options as $option) {
$availabilityString = isset($available)
? 'available'
: 'not available';
echo "$option[0] - $option[1] - $availabilityString\n";
}
Performance:
- Execution time:
- min: 0.00000691413879395s
- max: 0.00018811225891113s
- avg: 0.0000229740142822s
- Memory usage: 396KB
If you still want to use the $unique
, you can still prepare an associative array for performance reasons:
$indexById = array_flip($unique);
foreach ($ct_all_house_options as $option) {
$availabilityString = isset($indexById[$option[0]])
? 'available'
: 'not available';
echo "$option[0] - $option[1] - $availabilityString\n";
}
Performance:
- Execution time:
- min: 0.00000905990600586s
- max: 0.00018906593322754s
- avg: 0.0000392961502075s
- Memory usage: 397KB
Using in_array
instead:
foreach ($ct_all_house_options as $option) {
$availabilityString = in_array($option[0], $unique)
? 'available'
: 'not available';
echo "$option[0] - $option[1] - $availabilityString\n";
}
Execution time:
- min: 0.0000100135803223s
- max: 0.0050561428070068s
- avg: 0.0000860285758972s
Memory usage: 396KB
I used PHP Sandbox to perform the tests. Of course, the execution time is not always the same.