Preys
Preys

Reputation: 103

array_push add value to an existing key

I have the following array called $zoo

Array
(
[0] => &dog&
[1] => *1*
[2] => one
[3] => &cat&
[4] => *2*
[5] => two
[6] => &mouse&
[7] => *3*
[8] => three
[9] => &dog&
[10] => *4*
[11] => four
)

and i need the following result:

Array
(
[&dog&] => Array
    (
        [0] => Array
            (
                [0] => *1*
                [1] => one
            )
        [1] => Array
            (
                [0] => *4*
                [1] => four
            )
    )
[&cat&] => Array
    (
        [0] => Array
            (
                [0] => *2*
                [1] => two
            )
    )
[&mouse&] => Array
    (
        [0] => Array
            (
                [0] => *3*
                [1] => three
            )
    )
)

This is what I have come up with but the problem is that for [&dog&] he gives me only the last value (namely 4, four) and not the first value (1, one)

$animals=array();
for ($i = 0; $i < count($zoo); $i++)
{
if($zoo[$i][0] === "&")
    {
    $name=$zoo[$i];
    if (isset($name))
        $animals[$name] = array($liste);
    else
        $animals[$name] = array($liste);
    $liste="";
    }
if($zoo[$i][0] !== "&")
    {        
    $number = $zoo[$i];
    $liste[] = $number;
    $animals[$name] = array($liste);
    }
}
print_r($animals);

this results in

Array
(
[&dog&] => Array
    (
        [0] => Array
            (
                [0] => *4*
                [1] => four
            )
    )
[&cat&] => Array
    (
        [0] => Array
            (
                [0] => *2*
                [1] => two
            )
    )
[&mouse&] => Array
    (
        [0] => Array
            (
                [0] => *3*
                [1] => three
            )
    )
)

can anyone point me in the good direction?

Upvotes: 1

Views: 418

Answers (2)

Levi Morrison
Levi Morrison

Reputation: 19552

A solution that works for an array that has any number of indices that should grouped. It simply searches for a & prefix and adds the new values to the animals entry.

    $zooAmp = array(
            '&dog&',
            '*1*',
            'one',
            '&cat&',
            '*2*',
            'two',
            '&mouse&',
            '*3*',
            'three',
            '&dog&',
            '*4*',
            'four'
    );

    $zooStar = array(
            '*1*',
            '&dog&',
            'one',
            '*2*',
            '&cat&',
            'two',
            '*3*',
            '&mouse&',
            'three',
            '*4*',
            '&dog&',
            'four'
    );

    function & refactor(array $unfactored) {
            $len = count($unfactored);
            $data = array();

            if ($len<3) {
                    return $data;
            }

            if ($unfactored[0][0]=='&') {
                    //this algorithm isn't too bad, just loop through and add the ones starting with
                    //'&' to the data, and write everything from that index down to the next '&'
                    //into the created index in data.

                    $i=0;
                    while ($i<$len) {
                            if (!array_key_exists($unfactored[$i], $data))
                                    $data[$unfactored[$i]] = array();

                            //save to $arr for easier reading and writing
                            $arr = &$data[$unfactored[$i]];

                            $index = count($arr);
                            $arr[$index] = array();

                            for ($c=$i+1; $c<$len && $unfactored[$c][0]!='&'; $c++) {
                                    $arr[$index][] = $unfactored[$c];
                            }


                            $i = $c;
                    }

            } elseif ($unfactored[0][0]=='*') {
                    //this algorithm is a bit harder, but not so bad since we've already done the
                    //basic algorithm above.  We just need to store the ones with a '*' and then
                    //add them back into the array after it's been created.

                    $i=0;
                    $unorganizedItem = NULL;

                    while ($i<$len) {
                            $key = $unfactored[$i];

                            if ($key[0]=='*') {
                                    $unorganizedItem = $key;
                                    $i++;
                            } elseif ($key[0]=='&') {
                                    if(!array_key_exists($key, $data))
                                            $data[$key] = array();

                                    //save to $arr for easier reading and writing
                                    $arr = &$data[$key];
                                    $index = count($arr);

                                    $arr[$index][] = $unorganizedItem;
                                    $unorganizedItem = null;

                                    for ($c=$i+1; $c<$len && $unfactored[$c][0]!='&'; $c++) {
                                            if ($unfactored[$c][0]=='*') {
                                                    $unorganizedItem = $unfactored[$c];
                                            } else {
                                                    $arr[$index][] = $unfactored[$c];
                                            }
                                    }

                                    $i = $c;

                            }
                    }

            }

            return $data;

    }

    print_r(refactor($zooAmp));
    print_r(refactor($zooStar));

Prints:

Array
(
    [&dog&] => Array
        (
            [0] => Array
                (
                    [0] => *1*
                    [1] => one
                )

            [1] => Array
                (
                    [0] => *4*
                    [1] => four
                )

        )

    [&cat&] => Array
        (
            [0] => Array
                (
                    [0] => *2*
                    [1] => two
                )

        )

    [&mouse&] => Array
        (
            [0] => Array
                (
                    [0] => *3*
                    [1] => three
                )

        )

)
Array
(
    [&dog&] => Array
        (
            [0] => Array
                (
                    [0] => *1*
                    [1] => one
                )

            [1] => Array
                (
                    [0] => *4*
                    [1] => four
                )

        )

    [&cat&] => Array
        (
            [0] => Array
                (
                    [0] => *2*
                    [1] => two
                )

        )

    [&mouse&] => Array
        (
            [0] => Array
                (
                    [0] => *3*
                    [1] => three
                )

        )

)

Upvotes: 1

AndreKR
AndreKR

Reputation: 33658

$animals = array();

$c = count($zoo)/3;
for ($i = 0 ; $i < $c ; $i++)
{
    $species = array_shift($zoo);
    $number = array_shift($zoo);
    $number_text = array_shift($zoo);

    $animals[$species] []= array($number, $number_text);
}

If you want the start of a new animal be triggered by the "&" in the text, there are several solutions. Here's mine:

$animals = array();
unset($current_animal);
foreach ($zoo as $text)
{
    if ($text{0} == '&')
    {
        // Insert an element for the new animal and get a reference to it
        $animals[$text] []= array();
        end($animals[$text]);
        $current_animal =& $animals[$text][key($animals[$text])];
    }
    else
        $current_animal []= $text;
}
unset($current_animal);

Upvotes: 2

Related Questions