操纵php数组

操纵php数组

问题描述:

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.

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

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

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

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....

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