1

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?

2
  • My solution does work as intended. . . let me know if it isn't enough for you. Commented Oct 13, 2011 at 8:24
  • @levi : this is exactly what I need. Let me add a problem with the following array: Array ( [0] => 1 [1] => &dog& [2] => one [3] => 2 [4] => &cat& [5] => two [6] => 3 [7] => &mouse& [8] => three [9] => 4 [10] => &dog& [11] => four ) and I need the SAME RESULT. so now the word between & still has to be the key but the number between * that precedes the word between & should be the first element of the array in the value. Commented Oct 13, 2011 at 13:17

2 Answers 2

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

6 Comments

Brittle, what if he has more than two values associated with each new key?
@herbert And where does it say that? Sure, he asked with that example, but it's clear from his implementation that he was searching based on &.
@Levi: It's clear from his question that he has an array in one form and wants it in another form. The OP never said it was an example. If it is then the OP needs to specify that.
@Herbert, I'm not going to argue it, but that looks a lot like sample data. . .
@Levi: I agree to disagree since the OP hasn't chimed in one way or the other.
|
1

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
                )

        )

)

12 Comments

Good robust and general solution. +1
@levi : this is exactly what I need. Let me add a problem with the following array: Array ( [0] => 1 [1] => &dog& [2] => one [3] => 2 [4] => &cat& [5] => two [6] => 3 [7] => &mouse& [8] => three [9] => 4 [10] => &dog& [11] => four ) and I need the same result. so now the word between & still has to be the key but the word between * should be the first element of array in the value.
@Preys, does it need to be the same function? And will the two formats ever mix?
@Levi no, these are two independant functions. They will not mix.
@Preys, can we assume that each sub-array will have the same number of elements? Meaning, &dog&[0] will have the same number of elements as &dog&[1]?
|

Your Answer

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

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.