1

I have an array that I'd like to restructure. I want to group items by turn. I can figure out how to extract data from the array using foreach($arr['history'] as $obj) my issue is with populating a new array using a loop.

Currently it looks like this:

Array ( 
[history] => Array ( 
    [id] => 23452435 
    [legend] => Array ( 

        [0] => Array ( 
            [player] => me 
            [turn] => 1 
            [card] => Array ( 
                [name] => foo 
            ) 
        ) 

        [1] => Array ( 
            [player] => me 
            [turn] => 1 
            [card] => Array ( 
                [name] => bar
            ) 
        ) 

        [2] => Array ( 
            [player] => opponent 
            [turn] => 1
            [card] => Array (
                [name] => derp 
            ) 
        ) 

        [3] => Array ( 
            [player] => opponent 
            [turn] => 2 
            [card] => Array ( 
                [name] => hoo
            ) 
        ) 
    ) 
))

I want it to look like the following, but I can't figure out how to automatically create and populate this structure. This is an array with a sub-array for each turn, containing an array for me and opponent

Array (
[0] => Array (
    [me] => Array (
        [0] => foo
        [1] => bar
    )
    [opponent] = Array (
        [0] => derp
    )

)
[1] => Array (
    [me] => Array ()
    [opponent] => Array (
        [0] => hoo
    )
))

3 Answers 3

1

Try this script which subtracts 1 from the turn value to declare the first level key and then the player value as the second level key, then pushes the card value as a new subarray element.

$result = [];
foreach ($data['history']['legend'] as $list) {
    $result[$list['turn'] - 1][$list['player']][] = $list['card']['name'];
}

Fiddle it! http://ideone.com/BtKOKJ

Sign up to request clarification or add additional context in comments.

1 Comment

This is what I needed. With a few adjustments I made it work for my dataset. Thanks :) Also for some reason I had to separate the foreach loop into two, one for each key.
1

You can just start adding data to the new array. PHP is extremely forgiving.

$historyByTurns = array();
foreach ($arr['history'] as $historyItem) {
    foreach ($historyItem['legend'] as $legendItem) {
        $turn = $legendItem['turn'];
        $player = $legendItem['player'];
        if (!array_key_exists($turn, $historyByTurns)) {
            $historyByTurns[$turn] = array();
        }
        if (!array_key_exists($player, $historyByTurns[$turn])) {
            $historyByTurns[$turn][$player] = array();
        }
        foreach ($legendItem as $card) {
            $historyByTurns[$turn][$player][] = $card['name'];
        }
    }
}

You will have to test it, as I have no way to do that ATM.

2 Comments

This answer provided the same result as the other answer, but both weren't 100% what I needed, but helped me understand my issue. A few adjustments made this work though. Thanks :)
It is not necessary to instantiate an empty parent array when pushing data into it with square brace syntax.
0

I'm demonstrate a solution implementing array destructuring syntax in a foreach() for convenience value access. Inside the loop body, a reference variable will be maintained to ensure that every unique turn contains a me and an opponent subarray. Pushing data into references avoids subtracting from the turn value to dictate keys (subtraction might produce non-indexed keys depending on turn values).

Code: (Demo)

$result = [];
foreach ($data['history']['legend'] as ['player' => $p, 'turn' => $t, 'card' => ['name' => $cn]]) {
    if (!isset($ref[$t])) {
        $ref[$t] = ['me' => [], 'opponent' => []];
        $result[] =& $ref[$t];
    }
    $ref[$t][$p][] = $cn;
}
var_export($result);

@Naveed's answer does not ensure that each group has a me and an opponent subarray.

@michaJlS's answer doesn't actually work at all when fed the asker's data.

Comments

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.