group and/or rewrite an existing array - php

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"
]
}
]

Related

How to get and manipulate values from multi dimensional array and display them in row wise

array(2) {
["storeData"]=> array(10) {
[0]=> array(18) {
["name"]=> string(7) "STORENAME 01"
["address"]=> string(19) "THIS IS ADDRESS 01"
["zip"]=> string(5) "33312"
["pricing"]=> array(1) {
[0]=> array(4) {
["price"]=> float(30.00)
}
}
["distance"]=> float(3.0000)
}
[1]=> array(18) {
["name"]=> string(7) "STORENAME 02"
["address"]=> string(19) "THIS IS ADDRESS 02"
["zip"]=> string(5) "33302"
["pricing"]=> array(1) {
[0]=> array(4) {
["price"]=> float(35.00)
}
}
["distance"]=> float(2.0000)
}
[2]=> array(18) {
["name"]=> string(7) "STORENAME 01"
["address"]=> string(19) "SAME STORE BUT AT DIFFERENT LOCATION"
["zip"]=> string(5) "33301"
["pricing"]=> array(1) {
[0]=> array(4) {
["price"]=> float(30.00)
}
}
["distance"]=> float(3.5000)
}
}
}
I want to make so
#1 - store name will display only once if there are more than one stores with same name.
#2 - Than all addresses of same store should display with that store.
#3 - Same store at different locations will have same price so price should display only once.
#4 - Want to display all above info row wise (using loop)
I tried following but not working properly. It gives me similar store names only once and gives different locations for that store too. But price is not displaying only once for each unique store name.
$cnt = 1;
if (is_array($json) && !empty($json))
{
foreach ($json as $key1 => $level1)
{
if (is_array($level1) && !empty($level1))
{
foreach ($level1 as $key2 => $level2)
{
if($cnt == 1)
{
$str_name = $level2['name'];
echo "----- ".$level2['name']." -----<br/>";
}
if($str_name == $level2['name'])
{
echo $level2['address']." - ";
echo $level2['zip']." - ";
}
else if($str_name != $level2['name'])
{
$str_name = $level2['name'];
echo "----- ".$level2['name']." -----<br/>";
echo $level2['address']." - ";
echo $level2['zip']." - ";
}
if (is_array($level2) && !empty($level2))
{
foreach ($level2 as $key3 => $level3)
{
if (is_array($level3) && !empty($level3))
{
foreach ($level3 as $key4 => $level4)
{
if($cnt == 1)
{
echo "<b>".$level4['price']."</b> <br/>";
}
if($str_name != $level2['name'])
{
echo "<b>".$level4['price']."</b> <br/>";
}
}
}
}
}
$cnt++;
}
}
}
}
So what changes should I do in my above to make it work as I mentioned above? Or please suggest completely different solution(s) if this is not going to work?
Not saying your code wont work but for me it is quite complex for what it is trying to solve.
I would split this task into 2 phases: 1. transform data to format you need. 2. Display the data as you see fit.
<?php
$data = [
"storeData"=> [
0=> [
"name"=>"STORENAME 01",
"address"=> "THIS IS ADDRESS 01",
"zip"=> "33312",
"pricing"=> [
0=> [
"price"=> 30.00,
],
],
"distance"=> 3.0000,
],
1=> [
"name"=> "STORENAME 02",
"address"=> "THIS IS ADDRESS 02",
"zip"=> "33302",
"pricing"=> [
0=> [
"price"=> 35.00,
],
],
"distance"=> 2.0000,
],
2=> [
"name"=> "STORENAME 01",
"address"=> "SAME STORE BUT AT DIFFERENT LOCATION",
"zip"=> "33301",
"pricing"=> [
0=> [
"price"=> 30.00,
],
],
"distance"=> 3.5000,
],
],
];
// 1. transform to what is needed
$stores = [];
foreach ($data['storeData'] as $store) {
if (!isset($stores[$store['name']])) {
$stores[$store['name']] = ['name' => $store['name'], 'price' => $store['pricing'][0]['price'], 'locations'=>[$store['address'] => ['address' => $store['address'], 'zip' => $store['zip']]]];
} else {
$stores[$store['name']]['locations'][$store['address']] = ['address' => $store['address'], 'zip' => $store['zip']];
}
}
var_dump($stores);
// 2. display
foreach ($stores as $store) {
echo 'store: '.$store['name'].PHP_EOL;
echo ' locations:'.PHP_EOL;
foreach ($store['locations'] as $location) {
echo ' '.$location['address'].' '.$location['zip'].PHP_EOL;
}
echo ' price: '.$store['price'].PHP_EOL;
}
This is the $stores variable:
array(2) {
["STORENAME 01"]=>
array(3) {
["name"]=>
string(12) "STORENAME 01"
["price"]=>
float(30)
["locations"]=>
array(2) {
["THIS IS ADDRESS 01"]=>
array(2) {
["address"]=>
string(18) "THIS IS ADDRESS 01"
["zip"]=>
string(5) "33312"
}
["SAME STORE BUT AT DIFFERENT LOCATION"]=>
array(2) {
["address"]=>
string(36) "SAME STORE BUT AT DIFFERENT LOCATION"
["zip"]=>
string(5) "33301"
}
}
}
["STORENAME 02"]=>
array(3) {
["name"]=>
string(12) "STORENAME 02"
["price"]=>
float(35)
["locations"]=>
array(1) {
["THIS IS ADDRESS 02"]=>
array(2) {
["address"]=>
string(18) "THIS IS ADDRESS 02"
["zip"]=>
string(5) "33302"
}
}
}
}
It is exacly what you requested: each entry is a store, each store has all locations, single price.
Now it can be displayed as you want (html, console output etc. I used console output and got):
store: STORENAME 01
locations:
THIS IS ADDRESS 01 33312
SAME STORE BUT AT DIFFERENT LOCATION 33301
price: 30
store: STORENAME 02
locations:
THIS IS ADDRESS 02 33302
price: 35
If you want html replace PHP_EOL with <br />
Edit: code without location addresses as keys:
// transform to what is needed
$stores = [];
foreach ($data['storeData'] as $store) {
if (!isset($stores[$store['name']])) {
$stores[$store['name']] = ['name' => $store['name'], 'price' => $store['pricing'][0]['price'], 'locations'=> [['address' => $store['address'], 'zip' => $store['zip']]]];
} else {
$stores[$store['name']]['locations'][] = ['address' => $store['address'], 'zip' => $store['zip']];
}
}
$stores:
array(2) {
["STORENAME 01"]=>
array(3) {
["name"]=>
string(12) "STORENAME 01"
["price"]=>
float(30)
["locations"]=>
array(2) {
[0]=>
array(2) {
["address"]=>
string(18) "THIS IS ADDRESS 01"
["zip"]=>
string(5) "33312"
}
[1]=>
array(2) {
["address"]=>
string(36) "SAME STORE BUT AT DIFFERENT LOCATION"
["zip"]=>
string(5) "33301"
}
}
}
["STORENAME 02"]=>
array(3) {
["name"]=>
string(12) "STORENAME 02"
["price"]=>
float(35)
["locations"]=>
array(1) {
[0]=>
array(2) {
["address"]=>
string(18) "THIS IS ADDRESS 02"
["zip"]=>
string(5) "33302"
}
}
}
}

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 foreach loop repeated entries

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);

How to remove items that exist in the array from object?

This is how my array looks like:
array(3) {
[0]=>
string(3) "600"
[1]=>
string(3) "601"
[2]=>
string(3) "603"
}
This is how my object looks like:
array(7) {
[0]=>
object(stdClass)#688 (6) {
["id"]=>
string(3) "601"
["name"]=>
string(10) "test8opkpo"
["avatar"]=>
string(85) "http://avatars/user/medium.png"
["url"]=>
string(86) "/index.php"
["isOnline"]=>
int(0)
["lastseen"]=>
string(11) "2 weeks ago"
}
[1]=>
object(stdClass)#689 (6) {
["id"]=>
string(3) "604"
["name"]=>
string(6) "nopita"
["avatar"]=>
string(85) "http://avatars/user/medium.png"
["url"]=>
string(82) "/index.php"
["isOnline"]=>
int(0)
["lastseen"]=>
string(10) "1 week ago"
}
[2]=>
object(stdClass)#690 (6) {
["id"]=>
string(3) "603"
["name"]=>
string(6) "test_b"
["avatar"]=>
string(85) "http://avatars/user/medium.png"
["url"]=>
string(82) "/index.php"
["isOnline"]=>
int(0)
["lastseen"]=>
string(11) "6 hours ago"
}
Now I want to remove from the object, each item's id that matches the value inside the array.
So final output of the object should not contain id's that present in the array given. How to do that?
I tried using array_diff_key and unset to no avail.
$contactArray[$i] represent each id in the object
if (in_array($contactArray[$i], $array)) {
$a = array_diff_key($results->contacts, [$i => $contactArray[$i]]);
}
I created my own set of examples to simulate what you want to happen on your array:
$x = array('600','601', '603');
$y = array(
array("id" => "600",
"name" => "test",
"avatar" => "image"
),
array("id" => "601",
"name" => "test1",
"avatar" => "image1"
),
array("id" => "602",
"name" => "test2",
"avatar" => "image2"
),
array("id" => "603",
"name" => "test3",
"avatar" => "image3"
),
array("id" => "604",
"name" => "test4",
"avatar" => "image4"
)
);
echo '<pre>';
var_dump($y);
echo '</pre>';
$new_arr_ = array();
for($i = 0, $ctr = count($y); $i < $ctr; $i++) {
if(!in_array($y[$i]["id"], $x)) {
$new_arr_[] = array($y[$i]["id"], $y[$i]["name"], $y[$i]["avatar"]);
}
}
echo '<pre>';
var_dump($new_arr_);
echo '</pre>';
Hope it helps.
If I understand you correctly the following should work:
$contactArray = array_filter($contactArray, function ($v) use ($array) {
return !in_array(isset($v->id)?$v->id:null, $array);
});

Get the array set which has a distinct value for key PHP

array(
[0]=> array(3)
{
[0]=> array(3)
{
["name"]=> string(1) "a" ,
["code"]=> string(3) "416" ,
["id"]=> string(2) "a1" ,
},
[1]=> array(3)
{
["name"]=> string(1) "a",
["code"]=> string(3) "522" ,
["id"]=> string(2) "a2",
},
[2]=> array(3)
{
["name"]=> string(1) "b" ,
["code"]=> string(3) "580" ,
["id"]=> string(2) "b1" ,
}
},
[1]=> array(3)
{
[0]=> array(3)
{
["name"]=> string(1) "a" ,
["code"]=> string(3) "416" ,
["id"]=> string(2) "a1" ,
},
[1]=> array(3)
{
["name"]=> string(1) "a" ,
["code"]=> string(3) "522" ,
["id"]=> string(2) "a2" ,
},
[2]=> array(3)
{
["name"]=> string(1) "b" ,
["code"]=> string(3) "899" ,
["id"]=> string(2) "b2",
}
}
);
I have array like this. All I need is for each array (e.g [0]=>array())
I will search for the arrays inside and get the array['code'] only for array set that has distinct name value.
Example for array[0]: I will get the array[0][2]['code'] because the array set of this particular array[0][2]['code'] has a unique 'name'
Assume in the below code $array is $arr[0] from your example:
$array = array(
array(
"name" => "a",
"code" => "416",
"id" => "a1"
),
array(
"name" => "a",
"code" => "522",
"id" => "a2"
),
array(
"name" => "b",
"code" => "580",
"id" => "b1"
)
);
$counts = array_count_values(
array_map(function (array $entry) { return $entry['name']; }, $array)
// or array_column($array, 'name') in PHP 5.5+
);
$uniqueNames = array_keys(
array_filter($counts, function ($count) { return $count == 1; })
);
$result = array_filter($array, function (array $entry) use ($uniqueNames) {
return in_array($entry['name'], $uniqueNames);
});
Not necessarily the super most efficient method, but straight forward and functional. It filters the array down to the entries where name exists only once. This may or may not fit your definition of "unique", it's rather unclear what variations in the input data you may have.

Categories