1

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.

asked Feb 1, 2019 at 17:52
2
  • 1
    If single value, what is your desired output? Do you want to add that single value in all the paths? Commented Feb 1, 2019 at 17:54
  • That is a good question, I added the answer in edited code. Commented Feb 1, 2019 at 18:03

5 Answers 5

2

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....
answered Feb 1, 2019 at 18:17
1
  • 1
    Great 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)); } } } Commented Feb 1, 2019 at 18:38
0

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);
answered Feb 1, 2019 at 18:14
1
  • This code works great. I have reduced 200+ lines of code to 10 :). Thank you Serge. Commented Feb 1, 2019 at 18:40
0

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

DEMO:https://3v4l.org/Zh6Ws

answered Feb 1, 2019 at 18:08
1
  • 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! Commented Feb 1, 2019 at 18:16
0

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);
answered Feb 1, 2019 at 18:16
1
  • This also works, great solution, thank you Tamilvannan for you help! Commented Feb 1, 2019 at 18:42
0

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));
answered Feb 1, 2019 at 19:18

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.