I need to create path structure, with the values that I am getting from the array:
Array
(
[machineAttribute] => Array
(
[0] => TTT 1000 S
[1] => TTT 1100 S
)
[technicalAttribute] => Array
(
[0] => Certificate
[1] => Software
)
[languageAttribute] => Array
(
[0] => English
[1] => Spanish
)
)
So, I need to create path that looks like this:
Array
(
[0] => TTT 1000 S/Certificate/English
[1] => TTT 1000 S/Certificate/Spanish
[2] => TTT 1000 S/Software/English
[3] => TTT 1000 S/Software/Spanish
[4] => TTT 1100 S/Certificate/English
[5] => TTT 1100 S/Certificate/Spanish
[6] => TTT 1100 S/Software/English
[7] => TTT 1100 S/Software/Spanish
)
This is a perfect scenario and I was able to solve this with nested foreach:
if (is_array($machineAttributePath))
{
foreach ($machineAttributePath as $machinePath)
{
if (is_array($technicalAttributePath))
{
foreach ($technicalAttributePath as $technicalPath)
{
if (is_array($languageAttributePath))
{
foreach ($languageAttributePath as $languagePath)
{
$multipleMachineValuesPath[] = $machinePath . '/' . $technicalPath . '/' . $languagePath);
}
}
}
}
}
return $multipleMachineValuesPath;
}
But, the problem begins, if the array returns mixed values, sometimes, single value, sometimes array. For example:
Array
(
[machineAttribute] => Array
(
[0] => TTT 1000 S
[1] => TTT 1100 S
[2] => TTT 1200 S
)
[technicalAttribute] => Certificate
[languageAttribute] => Array
(
[0] => English
[1] => Spanish
)
)
Then the array should look like:
Array
(
[0] => TTT 1000 S/Certificate/English
[1] =>TTT 1000 S/Certificate/Spanish
[2] => TTT 1100 S/Certificate/English
[3] => TTT 1100 S/Certificate/Spanish
)
I wrote code, but it is really messy and long and not working properly. I am sure that this could be somehow simplified but I have enough knowledge to solve this. If someone knows how to deal with this situation, please help. Thank you.
-
1If single value, what is your desired output? Do you want to add that single value in all the paths?Tamilvanan– Tamilvanan2019年02月01日 17:54:28 +00:00Commented Feb 1, 2019 at 17:54
-
That is a good question, I added the answer in edited code.user6761319– user67613192019年02月01日 18:03:12 +00:00Commented Feb 1, 2019 at 18:03
5 Answers 5
You can convert any single value to array just by
(array) $val
In the same time, if $val is already array, it will be not changed
So, you can a little change all foreach
foreach((array) $something....
-
1Great and so simple...:) Tried and working like charm.,
$pathArr = array(); foreach($arr['machineAttribute'] as $m) { foreach($arr['technicalAttribute'] as $t) { foreach((array) $arr['languageAttribute'] as $l) { $pathArr[] = implode('/',array($m,$t,$l)); } } }
Tamilvanan– Tamilvanan2019年02月01日 18:38:30 +00:00Commented Feb 1, 2019 at 18:38
If you need something simple, you can convert your scalar values to array by writing simple separate function (let name it "force_array"). The function that wraps argument to array if it is not array already.
function force_array($i) { return is_array($i) ? $i : array($i); }
//...
foreach (force_array($machineAttributePath) as $machinePath)
{
foreach (force_array($technicalAttributePath) as $technicalPath)
{
foreach (force_array($languageAttributePath) as $languagePath)
{
$multipleMachineValuesPath[] = $machinePath . '/' . $technicalPath . '/' . $languagePath;
}
}
}
return($multipleMachineValuesPath);
-
This code works great. I have reduced 200+ lines of code to 10 :). Thank you Serge.user6761319– user67613192019年02月01日 18:40:04 +00:00Commented Feb 1, 2019 at 18:40
You can do this way also without messing up. Just create the Cartesian of your input array and finally implode the generated array with /
. Hope this helps :)
<?php
function cartesian($input) {
$result = array();
while (list($key, $values) = each($input)) {
if (empty($values)) {
continue;
}
if (empty($result)) {
foreach($values as $value) {
$result[] = array($key => $value);
}
}
else {
$append = array();
foreach($result as &$product) {
$product[$key] = array_shift($values);
$copy = $product;
foreach($values as $item) {
$copy[$key] = $item;
$append[] = $copy;
}
array_unshift($values, $product[$key]);
}
$result = array_merge($result, $append);
}
}
return $result;
}
$data = array
(
'machineAttribute' => array
(
'TTT 1000 S',
'TTT 1100 S'
),
'technicalAttribute' => array
(
'Certificate',
'Software'
),
'languageAttribute' => array
(
'English',
'Spanish',
)
);
$combos = cartesian($data);
$final_result = [];
foreach($combos as $combo){
$final_result[] = implode('/',$combo);
}
print_r($final_result);
-
Thank you for that. That is some serious array manipulation. I tested your demo, it works good with array values, but it has errors when there is a single value, however I will try to adopt the code. Thank you for great idea!user6761319– user67613192019年02月01日 18:16:29 +00:00Commented Feb 1, 2019 at 18:16
This will solve your problem almost.
$arr['machineAttribute'] = (array) $arr['machineAttribute'];
$arr['technicalAttribute'] = (array) $arr['technicalAttribute'];
$arr['languageAttribute'] = (array) $arr['languageAttribute'];
$machCount = count($arr['machineAttribute']);
$techCount = count($arr['technicalAttribute']);
$langCount = count($arr['languageAttribute']);
$attr = [];
for($i=0;$i<$machCount;$i++) {
$attr[0] = $arr['machineAttribute'][$i] ?? "";
for($j=0;$j<$techCount;$j++) {
$attr[1] = $arr['technicalAttribute'][$j] ?? "";
for($k=0;$k<$langCount;$k++) {
$attr[2] = $arr['languageAttribute'][$k] ?? "";
$pathArr[] = implode('/',array_filter($attr));
}
}
}
print_r($pathArr);
-
This also works, great solution, thank you Tamilvannan for you help!user6761319– user67613192019年02月01日 18:42:31 +00:00Commented Feb 1, 2019 at 18:42
This works too!
$results = [[]];
foreach ($arrays as $index => $array) {
$append = [];
foreach ($results as $product) {
foreach ($array as $item) {
$product[$index] = $item;
$append[] = $product;
}
}
$results = $append;
}
print_r(array_map(function($arr){ return implode('/',$arr);},$results));