Stack Stack - 5 months ago 10
PHP Question

How can I print some arrays asymmetrically?

I have three arrays like these:

$arr1 = array ("one", "two");
$arr2 = array ("red", "blue", "white", "green", "pink");
$arr3 = array ("1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12", "13");


And I'm trying to print something like this:

one - red - 1
one - red - 2
one - red - 3
one - blue - 4
one - blue - 5
one - white - 6
one - white - 7
one - white - 8
one - white - 9
two - green - 10
two - pink - 11
two - pink 12
two - pink 13


As you see there isn't any discipline. That's just a constant sequence which is out of sorts. In reality those arrays are much bigger and I cannot handle them manually. All I want to know how can I manage such a thing? And what should I do in this situation?

I usually do such things by nested loops. But now there isn't any order ..! How can I do that now?

Answer

Based on your comment, there is some additional information about the 'structure' of these arrays:

Yes there is no order .. but its structure is always constant ..! I mean always first item of $arr1 should be printed 9 times and its second item 4 times ..! And so on for other arrays ...

Which you didn't provide, but let's make it look like the output in your answer.

$arr1 = array("one", "two");
$arr2 = array("red", "blue", "white", "green", "pink");
$arr3 = array("1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12", "13");

$structure = array(
     array(9, 4), // sequence lengths for $arr1
                  // = repeat first item 9 times, second 4 times
     array(3, 2, 4, 1, 3), // for $arr2
     array(1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1), // for $arr3
);

function createOutput($arrays, $structure, $length){
    $ret = array();
    $seq_pos = array();
    $seq_iter = array();
    for ($i = 0; $i < count($structure); $i++){
        $seq_pos[$i] = 0;
        $seq_iter[$i] = 0;
    }
    for ($i = 0; $i < $length; $i++){
        $ret[$i] = array();
        for ($j = 0; $j < count($structure); $j++){
            $ret[$i][$j] = $arrays[$j][$seq_pos[$j]];
            $seq_iter[$j]++;
            if ($seq_iter[$j] >= $structure[$j][$seq_pos[$j]]){
                $seq_iter[$j] = 0;
                $seq_pos[$j]++;
                if ($seq_pos[$j] >= count($structure[$j])){
                    $seq_pos[$j] = 0;
                }
            }
        }
    }
    return $ret;
}

$out = createOutput(
    array($arr1, $arr2, $arr3),
    $structure,
    13
);
for ($i = 0; $i < count($out); $i++){
    echo implode($out[$i], " - ")."\n";
}

Which produces:

one - red - 1
one - red - 2
one - red - 3
one - blue - 4
one - blue - 5
one - white - 6
one - white - 7
one - white - 8
one - white - 9
two - green - 10
two - pink - 11
two - pink - 12
two - pink - 13

The way the function works is that it keeps iterators of sorts for each of the arrays. It will step to the next position in the array if the item has been repeated enough times. Once again, you didn't really provide enough information in your answer, but you did insist that the structure is constant. If it is so, you need to fine-tune (or generate) the $structure array based on the lengths of the sequences you want.