Reputation: 171
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
)
))
Upvotes: 1
Views: 1802
Reputation: 166
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
Upvotes: 1
Reputation: 47894
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.
Upvotes: 0
Reputation: 2500
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.
Upvotes: 1