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.

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....
Sign up to request clarification or add additional context in comments.

1 Comment

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

1 Comment

This code works great. I have reduced 200+ lines of code to 10 :). Thank you Serge.
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

1 Comment

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

1 Comment

This also works, great solution, thank you Tamilvannan for you help!
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));

Comments

Your Answer

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