PHP foreach loop repeated entries - php

I need help in order to manipulate a multidimensional array during PHP foreach loop. I have the array below:
$sports = [
[
"id" => "soccer",
"name" => "Football",
"categories" => [
[
"id" => "s1",
"name" => "category 1",
"sportID" => "soccer"
],
[
"id" => "s2",
"name" => "category 2",
"sportID" => "soccer"
],
],
"img" => "/test.png"
],
[
"id" => "tennis",
"name" => "Tennis",
"categories" => [
[
"id" => "t1",
"name" => "category 1",
"sportID" => "tennis"
],
[ "id" => "t2",
"name" => "category 2",
"sportID" => "tennis"
],
],
"img" => "/test.png"
],
];
I have the below foreach in order to take all the sports with the corresponding categories for every sport,
foreach($sports as $s){
$categories = $s['categories'];
foreach($categories as $c){
$cats[] = [
"id" => $c['id'],
"name" => $c['name'],
"sportID" => $s['id'],
];
}
$allCategories[] = $cats;
$data[] = [
"id" => $s['id'],
"name" => $s['name'],
"categories" => $cats,
"img" => $s['img'],
];
$output[] = $data;
}
but the output is not what I expected; instead, I am getting repeated results like the one below:
array(2) {
[0]=>
array(1) {
[0]=>
array(4) {
["id"]=>
string(8) "soccer"
["name"]=>
string(8) "Football"
["categories"]=>
array(2) {
[0]=>
array(3) {
["id"]=>
string(2) "s1"
["name"]=>
string(10) "category 1"
["sportID"]=>
string(8) "soccer"
}
[1]=>
array(3) {
["id"]=>
string(2) "s2"
["name"]=>
string(10) "category 2"
["sportID"]=>
string(8) "soccer"
}
}
["img"]=>
string(9) "/test.png"
}
}
[1]=>
array(2) {
[0]=>
array(4) {
["id"]=>
string(8) "soccer"
["name"]=>
string(8) "Football"
["categories"]=>
array(2) {
[0]=>
array(3) {
["id"]=>
string(2) "s1"
["name"]=>
string(10) "category 1"
["sportID"]=>
string(8) "soccer"
}
[1]=>
array(3) {
["id"]=>
string(2) "s2"
["name"]=>
string(10) "category 2"
["sportID"]=>
string(8) "soccer"
}
}
["img"]=>
string(9) "/test.png"
}
[1]=>
array(4) {
["id"]=>
string(10) "tennis"
["name"]=>
string(8) "Tennis"
["categories"]=>
array(4) {
[0]=>
array(3) {
["id"]=>
string(2) "s-1"
["name"]=>
string(10) "category 1"
["sportID"]=>
string(8) "soccer"
}
[1]=>
array(3) {
["id"]=>
string(2) "s2"
["name"]=>
string(10) "category 2"
["sportID"]=>
string(8) "soccer"
}
[2]=>
array(3) {
["id"]=>
string(2) "t1"
["name"]=>
string(10) "category 1"
["sportID"]=>
string(10) "tennis"
}
[3]=>
array(3) {
["id"]=>
string(2) "t2"
["name"]=>
string(10) "category 2"
["sportID"]=>
string(10) "tennis"
}
}
["img"]=>
string(9) "/test.png"
}
}
}
As you can imagine this is not the correct output, as in the categories of the tennis you can see the categories of the soccer also.
How can I correct my foreach loop in order to get the correct output?

You forget to reset $cats and $data arrays.
<?php
$sports = [
[
"id" => "soccer",
"name" => "Football",
"categories" => [
[
"id" => "s1",
"name" => "category 1",
"sportID" => "soccer"
],
[
"id" => "s2",
"name" => "category 2",
"sportID" => "soccer"
],
],
"img" => "/test.png"
],
[
"id" => "tennis",
"name" => "Tennis",
"categories" => [
[
"id" => "t1",
"name" => "category 1",
"sportID" => "tennis"
],
[ "id" => "t2",
"name" => "category 2",
"sportID" => "tennis"
],
],
"img" => "/test.png"
],
];
foreach($sports as $s){
$categories = $s['categories'];
# before inner loop we need to reset both arrays
$cats = [];
$data = [];
foreach($categories as $c){
$cats[] = [
"id" => $c['id'],
"name" => $c['name'],
"sportID" => $s['id'],
];
}
$allCategories[] = $cats;
$data[] = [
"id" => $s['id'],
"name" => $s['name'],
"categories" => $cats,
"img" => $s['img'],
];
$output[] = $data;
}
echo '<PRE>';
print_r($output);

Related

How to convert Multidimensional array to Associative array in PhP?

I need to convert the multidimensional array to an associative array.
Please help me to convert the array. Need to remove the keys "sub_code" & "credits" and make the first string as "key" & the second string as "value". I tried a lot of ways but I failed.
Need to convert the below array.
array(9) {
[0]=> array(2)
{
["sub_code"] => string(6) "HS6151"
["credits"] => string(1) "4"
}
[1]=> array(2)
{
["sub_code"] => string(6) "MA6151"
["credits"] => string(1) "4"
}
[2]=> array(2)
{
["sub_code"] => string(6) "PH6151"
["credits"] => string(1) "3"
}
[3]=> array(2)
{
["sub_code"] => string(6) "CY6151"
["credits"] => string(1) "3"
}
[4]=> array(2)
{
["sub_code"] => string(6) "GE6151"
["credits"] => string(1) "3"
}
[5]=> array(2)
{
["sub_code"] => string(6) "GE6152"
["credits"] => string(1) "4"
}
[6]=> array(2)
{
["sub_code"] => string(6) "GE6161"
["credits"] => string(1) "2"
}
[7]=> array(2)
{
["sub_code"] => string(6) "GE6162"
["credits"] => string(1) "2"
}
[8]=> array(2)
{
["sub_code"] => string(6) "GE6163"
["credits"] => string(1) "1"
}
}
Like below.
array(9) {
["HS6151"] => string(1) "4"
["MA6151"] => string(1) "4"
["PH6151"] => string(1) "3"
["CY6151"] => string(1) "3"
["GE6151"] => string(1) "3"
["GE6152"] => string(1) "4"
["GE6161"] => string(1) "2"
["GE6162"] => string(1) "2"
["GE6163"] => string(1) "1"
}
You can use array_column like so:
$array = [
[
'sub_code' => 'HS6151',
'credits' => '4',
],
[
'sub_code' => 'MA6151',
'credits' => '4',
],
];
$result = array_column($array, 'credits', 'sub_code');
print_r($result);
Results in:
Array
(
[HS6151] => 4
[MA6151] => 4
)
Sounds pretty straight forward:
<?php
$input = [
[
"sub_code" => "HS6151",
"credits" => "4"
], [
"sub_code" => "MA6151",
"credits" => "4"
], [
"sub_code" => "PH6151",
"credits" => "3"
], [
"sub_code" => "CY6151",
"credits" => "3"
], [
"sub_code" => "GE6151",
"credits" => "3"
], [
"sub_code" => "GE6152",
"credits" => "4"
], [
"sub_code" => "GE6161",
"credits" => "2"
], [
"sub_code" => "GE6162",
"credits" => "2"
], [
"sub_code" => "GE6163",
"credits" => "1"
]
];
$output = [];
array_walk($input, function($entry) use (&$output) {
$output[$entry["sub_code"]] = $entry["credits"];
});
print_r($output);
The output obviously is:
Array
(
[HS6151] => 4
[MA6151] => 4
[PH6151] => 3
[CY6151] => 3
[GE6151] => 3
[GE6152] => 4
[GE6161] => 2
[GE6162] => 2
[GE6163] => 1
)

array_input is the array which can be dynamic up to any level, I want to convert input array into the array_output format using php

Input Array : Input array is like below and level in it can be dynamic up to any level,
$array_input = [
0 => ["level" => "L1", "points" => 1000],
1 => ["level" => "L1", "points" => 5000],
2 => ["level" =>"L2 ", "points" => 3000],
3 => ["level" => "L3", "points" => 4000],
4 => ["level" => "L3", "points" => 6000],
5 => ["level" => "L2", "points" => 4000],
6 => ["level" => "L2", "points" => 5000],
7 => ["level" => "L2", "points" => 5000],
8 => ["level" => "L1", "points" => 6000],
9 => ["level" => "L1", "points" => 2000]
];
OUTPUT ARRAY: Output array should be like below, I tried using 2 foreach loop and accessing previous Level and compare it to next Level. But it is creating problem where Level is more than 2 times.
$array_output = [
0 => [
0 => ["level" => "L1", "points" => 1000],
1 => ["level" => "L1", "points" => 5000]
],
1 => [
0 => ["level" => "L2", "points" => 3000]
],
2 => [
0 => ["level" => "L3", "points" => 4000],
1 => ["level" => "L3", "points" => 6000]
],
3 => [
0 => ["level" => "L2", "points" => 4000],
1 => ["level" => "L2", "points" => 5000],
2 => ["level" => "L2", "points" => 5000]
],
4 => [
0 => ["level" => "L1", "points" => 6000],
1 => ["level" => "L1", "points" => 2000]
]
];
This is the code i tried but it's not giving result what i want:
$opArr = [];
$i=1;
$justArr = [];
$pre = $array_input[0]['level'];
$firstArr = $array_input[0];
for($i; $i<count($array_input); $i++){ // 0
foreach($array_input[$i] as $key => $value){
if($key == 'level'){
$level = $value;
}
}
if($pre == $level ){
$opArr[] = $firstArr;
$opArr[] = $array_input[$i];
}
$pre = $array_input[$i]['level'];
$firstArr = $array_input[$i];
}
echo "<pre>";
echo "OpArr:";
print_r($opArr);
echo "<pre>";
You may give this a try. See comments for step-by-step explanation. Outputs:
array(5) {
[0]=>
array(2) {
[0]=>
array(2) {
["level"]=>
string(2) "L1"
["points"]=>
int(1000)
}
[1]=>
array(2) {
["level"]=>
string(2) "L1"
["points"]=>
int(5000)
}
}
[1]=>
array(1) {
[0]=>
array(2) {
["level"]=>
string(2) "L2"
["points"]=>
int(3000)
}
}
[2]=>
array(2) {
[0]=>
array(2) {
["level"]=>
string(2) "L3"
["points"]=>
int(4000)
}
[1]=>
array(2) {
["level"]=>
string(2) "L3"
["points"]=>
int(6000)
}
}
[3]=>
array(3) {
[0]=>
array(2) {
["level"]=>
string(2) "L2"
["points"]=>
int(4000)
}
[1]=>
array(2) {
["level"]=>
string(2) "L2"
["points"]=>
int(5000)
}
[2]=>
array(2) {
["level"]=>
string(2) "L2"
["points"]=>
int(5000)
}
}
[4]=>
array(2) {
[0]=>
array(2) {
["level"]=>
string(2) "L1"
["points"]=>
int(6000)
}
[1]=>
array(2) {
["level"]=>
string(2) "L1"
["points"]=>
int(2000)
}
}
}
Code:
<?php
// Your input array.
$array_input = [
0 => ["level" => "L1", "points" => 1000],
1 => ["level" => "L1", "points" => 5000],
2 => ["level" =>"L2", "points" => 3000],
3 => ["level" => "L3", "points" => 4000],
4 => ["level" => "L3", "points" => 6000],
5 => ["level" => "L2", "points" => 4000],
6 => ["level" => "L2", "points" => 5000],
7 => ["level" => "L2", "points" => 5000],
8 => ["level" => "L1", "points" => 6000],
9 => ["level" => "L1", "points" => 2000]
];
$output = [];
// Keep track of last group key seen so we can
// create a new child array on every boundary.
$lastGroupKey = $array_input[0]['level'];
// Output array.
$grouped = [];
// Loop over every input element.
foreach ($array_input as $input)
{
// Grouping on 'level' value, which we'll use as a 'key'.
$groupKey = $input['level'];
// If current key is not the last one seen, then this is a
// boundary. Push the current group onto the output
// and start afresh.
if ($groupKey !== $lastGroupKey)
{
$output[] = $grouped;
$grouped = [];
}
// Record each row.
$grouped[] = $input;
// Update last key seen.
$lastGroupKey = $groupKey;
}
// The end of the array is the final boundary.
// Record trailing group.
$output[] = $grouped;
var_dump($output);
/*
array(5) {
[0]=>
array(2) {
[0]=>
array(2) {
["level"]=>
string(2) "L1"
["points"]=>
int(1000)
}
[1]=>
array(2) {
["level"]=>
string(2) "L1"
["points"]=>
int(5000)
}
}
[1]=>
array(1) {
[0]=>
array(2) {
["level"]=>
string(2) "L2"
["points"]=>
int(3000)
}
}
[2]=>
array(2) {
[0]=>
array(2) {
["level"]=>
string(2) "L3"
["points"]=>
int(4000)
}
[1]=>
array(2) {
["level"]=>
string(2) "L3"
["points"]=>
int(6000)
}
}
[3]=>
array(3) {
[0]=>
array(2) {
["level"]=>
string(2) "L2"
["points"]=>
int(4000)
}
[1]=>
array(2) {
["level"]=>
string(2) "L2"
["points"]=>
int(5000)
}
[2]=>
array(2) {
["level"]=>
string(2) "L2"
["points"]=>
int(5000)
}
}
[4]=>
array(2) {
[0]=>
array(2) {
["level"]=>
string(2) "L1"
["points"]=>
int(6000)
}
[1]=>
array(2) {
["level"]=>
string(2) "L1"
["points"]=>
int(2000)
}
}
}
*/
in cycle: if element first or next element exists and have different "level" then create new element(sub-array) in result array

PHP indexed array to nested associative array

I need to convert simple array to nested array according to specific rules. I've achived it but I'm looking for better solution.
SIMPLE:
array(4) {
[0]=>
array(2) {
["id"]=>
string(2) "11"
["type"]=>
int(3)
}
[1]=>
array(2) {
["id"]=>
string(2) "10"
["type"]=>
int(2)
}
[2]=>
array(2) {
["id"]=>
string(1) "1"
["type"]=>
int(1)
}
[3]=>
array(2) {
["id"]=>
string(1) "0"
["type"]=>
int(1)
}
}
EXPECTED EFFECT:
array(1) {
[0]=>
array(2) {
["type"]=>
int(1)
["child"]=>
array(1) {
[1]=>
array(2) {
["type"]=>
int(1)
["child"]=>
array(1) {
[10]=>
array(2) {
["type"]=>
int(2)
["child"]=>
array(1) {
[11]=>
array(2) {
["type"]=>
int(3)
["child"]=>
array(0) {
}
}
}
}
}
}
}
}
}
MY SOLUTION (not very satisfying):
$nestedArray = [];
foreach ($simpleArray as $item)
{
if (!empty($nestedArray))
{
$array = $nestedArray;
reset($array);
$firstKey = key($array);
}
$nestedArray[$item['id']]['child'] = $nestedArray;
$nestedArray[$item['id']]['type'] = $item['type'];
if (!empty($firstKey))
{
unset($nestedArray[$firstKey]);
}
}
As I said, I'm looking for more elegant way to achieve that. Rule are very simply: every next item is child of previous.
You could use recursion:
function nest($arr) {
return count($arr) ? ["type" => array_pop($arr)["type"], "child" => nest($arr)] : [];
}
With your example input, it would look like this:
$simpleArray = [
["id" => "11", "type" => 3],
["id" => "10", "type" => 2],
["id" => "1", "type" => 1],
["id" => "0", "type" => 1]
];
function nest($arr) {
return count($arr) ? ["type" => array_pop($arr)["type"], "child" => nest($arr)] : [];
}
$nested = nest($simpleArray));
$nested will have the following value:
[
"type" => 1,
"child" => [
"type" => 1,
"child" => [
"type" => 2,
"child" => [
"type" => 3,
"child" => []
]
]
]
]

PHP: manipulate array making value as key recursively

I got this array:
array:2 [▼
0 => array:1 [▼
0 => array:7 [▼
"id" => "1"
"producer" => "Samsung"
"model" => "LE22B541C4W"
"category" => "1"
"production_date" => "2009-05-08"
"status" => "Discontinued"
"type" => "LCD"
]
]
1 => array:1 [▼
0 => array:7 [▼
"id" => "2"
"producer" => "Samsung"
"model" => "P24FHD"
"category" => "1"
"production_date" => "0000-00-00"
"status" => "Discontinued"
"type" => "LCD"
]
]
[...]
]
I would like to take the "ID" value of each array and make as primary key and remove the useless keys like this
array:2 [
1 => array:7 [
"id" => "1"
"producer" => "Samsung"
"model" => "LE22B541C4W"
"category" => "1"
"production_date" => "2009-05-08"
"status" => "Discontinued"
"type" => "LCD"
]
2 => array:7 [
[...]
By now I'm just populate the array using this simple query and a for loop:
foreach ($compatibility as $compElement) {
$sql = "SELECT * FROM product WHERE ID = '$compElement';";
$em = $this->getDoctrine()->getManager();
$stmt = $em->getConnection()->prepare($sql);
$stmt->execute();
$thisElement = $stmt->fetchAll();
$compArray[] = $thisElement;
}
You can do something like this if you don't want to change how you populate your array:
$result = call_user_func_array(
'array_merge_recursive',
$array
);
Output
array(2) {
[0]=>
array(7) {
["id"]=>
string(1) "1"
["producer"]=>
string(7) "Samsung"
["model"]=>
string(11) "LE22B541C4W"
["category"]=>
string(1) "1"
["production_date"]=>
string(10) "2009-05-08"
["status"]=>
string(12) "Discontinued"
["type"]=>
string(3) "LCD"
}
[1]=>
array(7) {
["id"]=>
string(1) "2"
["producer"]=>
string(7) "Samsung"
["model"]=>
string(6) "P24FHD"
["category"]=>
string(1) "1"
["production_date"]=>
string(10) "0000-00-00"
["status"]=>
string(12) "Discontinued"
["type"]=>
string(3) "LCD"
}
}

group and/or rewrite an existing array

I'm using a database system for some kind of gaming competition where players can team up and participate in events. Right now players have their own database, then there is a database for teams (team id, name, join password, etc) and a database where I save which player (player name/id is in which team name/id). My database call gives me an array with team_name, username, etc. I wanted to group the users by a common team_name value which worked, but I'm not able to rewrite it according to my needs.
I want to build some kind of api for my personal use in C# application. There I want the output of my script to be json and I want to show all the teams with some details. Right now im using the following code:
$team_keys = array();
foreach ($team_data AS $k => $sub_array)
{
$this_team = $sub_array['team_name'];
$team_keys[$this_team][$k] = array('username' => $sub_array['username']);
}
echo json_encode($team_keys, JSON_PRETTY_PRINT);
This gives me an output like this:
{
"Team1": {
"0": {
"username": "player1"
},
"1": {
"username": "player2"
},
"22": {
"username": "player3"
}
},
"Team2": {
"2": {
"username": "player4"
},
"3": {
"username": "player5"
}, .....
}
But I want to achieve something like:
{
"team_name": "Team1",
"team_password": "secret",
"creation_timestamp": "123456789",
"players": [
"Player1",
"Player2",
"Player3"
]
}, ....
I tried tons of different approaches but I was simply not able to regroup and rewrite the array to my needs. Hopefully someone can help me out.
EDIT: $team_data looks like this (I'm using JOIN to join my user, teams, and team_member tables to get all the data together):
array(83) {
[0]=>
array(4) {
["username"]=>
string(8) "Player1"
["team_name"]=>
string(8) "Team1"
["team_password"]=>
string(7) "secret"
["team_id"]=>
string(1) "1"
}
[1]=>
array(4) {
["username"]=>
string(11) "Player2"
["team_name"]=>
string(8) "Team1"
["team_password"]=>
string(7) "secret"
["team_id"]=>
string(1) "1"
}
[2]=>
array(4) {
["username"]=>
string(8) "Player3"
["team_name"]=>
string(10) "Team2"
["team_password"]=>
string(6) "ultrasecret"
["team_id"]=>
string(1) "2"
},...
So Input was the following data
array(4) {
[0]=>
array(4) {
["team_name"]=>
string(5) "Team1"
["username"]=>
string(7) "player1"
["team_password"]=>
string(6) "secret"
["team_id"]=>
int(1)
}
[1]=>
array(4) {
["team_name"]=>
string(5) "Team1"
["username"]=>
string(7) "player2"
["team_password"]=>
string(6) "secret"
["team_id"]=>
int(1)
}
[2]=>
array(4) {
["team_name"]=>
string(5) "Team2"
["username"]=>
string(7) "player1"
["team_password"]=>
string(6) "secret"
["team_id"]=>
int(2)
}
[3]=>
array(4) {
["team_name"]=>
string(5) "Team2"
["username"]=>
string(7) "player2"
["team_password"]=>
string(6) "secret"
["team_id"]=>
int(2)
}
}
This is my code with my testset of $team_data
<?php
$team_data = array(array('team_name' => 'Team1', 'username' => 'player1', 'team_password' => 'secret', 'team_id' => 1)
,array('team_name' => 'Team1', 'username' => 'player2', 'team_password' => 'secret', 'team_id' => 1)
,array('team_name' => 'Team2', 'username' => 'player1', 'team_password' => 'secret', 'team_id' => 2)
,array('team_name' => 'Team2', 'username' => 'player2', 'team_password' => 'secret', 'team_id' => 2)
);
$team_keys = array();
foreach ($team_data AS $player_dara) {
if (!isset($team_keys[$player_dara['team_id']])) {
$team_keys[$player_dara['team_id']] = array();
$team_keys[$player_dara['team_id']]['team_name'] = $player_dara['team_name'];
$team_keys[$player_dara['team_id']]['team_id'] = $player_dara['team_id'];
$team_keys[$player_dara['team_id']]['secret'] = $player_dara['secret'];
$team_keys[$player_dara['team_id']]['players'] = array();
}
$team_keys[$player_dara['team_id']]['players'][] = $player_dara['username'];
}
echo json_encode(array_values($team_keys), JSON_PRETTY_PRINT);
Output
[
{
"team_name": "Team1",
"team_id": 1,
"secret": null,
"players": [
"player1",
"player2"
]
},
{
"team_name": "Team2",
"team_id": 2,
"secret": null,
"players": [
"player1",
"player2"
]
}
]

Categories