I've got an multi-array (currently with objects) that I want to reorder based on a specific key/value.
Array
(
[0] => stdClass Object
(
[task_id] => 1
[task_title] => Title
[users_username] => John
)
[1] => stdClass Object
(
[task_id] => 2
[task_title] => Title
[users_username] => John
)
[2] => stdClass Object
(
[task_id] => 3
[task_title] => Title
[users_username] => Mike
)
)
I'd like to reorder it to get multi-arrays by user_name, so I can cycle through the task by username.
Array
(
[John] => Array
(
[0] => Array
(
[task_id] => 1
[title] => Title
)
[1] => Array
(
[task_id] => 2
[title] => Title
)
)
[Mike] => Array
(
[0] => Array
(
[task_id] => 3
[title] => Title
)
)
)
Is it possible to recreate my array to an array like that above?
Updated version of the code
<?php
$it0 = (object) array('task_id' => 1,'task_title' => 'Title','users_username' => 'John');
$it1 = (object) array('task_id' => 2,'task_title' => 'Title','users_username' => 'John');
$it2 = (object) array('task_id' => 3,'task_title' => 'Title','users_username' => 'Mike');
$array = array($it0,$it1,$it2);
$return = array();
foreach($array as $id => $value){
$return[$value->users_username][] = array('task_id' => $value->task_id,'title' => $value->task_title);
}
var_dump($return);
Yes, it is possible.
You'll have to loop through your current array and create a new array to do it.
example:
$new_array = array();
foreach ($array as $row)
{
$new_row = array(
'task_id' => $row->task_id,
'title' => $row->task_title,
);
$name = $row->users_username;
if (isset($new_array[$name]))
{
$new_array[$name][] = $new_row;
}
else
{
$new_array[$name] = array($new_row);
}
}
Now $new_array contains the new array exactly like the one you're asking for.
Then you can sort it with
ksort($new_array);
There may be another way to do this, with some built-in function, but sometimes I'd rather just do it myself, and know how it is working, without having to look up the documentation.
The approach:
Iterate through all of the first array, looking at [users_username] and putting them into a new array.
Code:
$dst_array = array();
foreach ($src_array as $val)
{
$user = $val->users_username;
// TODO: This check may be unnecessary. Have to test to find out.
// If this username doesn't already have an array in the destination...
if (!array_key_exists($user, $dst_array))
$dst_array[$user] = array(); // Create a new array for that username
// Now add a new task_id and title entry in that username's array
$dst_array[$user][] = array(
'task_id' => $val->task_id
'title' => $val->title
);
}
Just something like this (maybe not 100% PHP code):
foreach ( $obj : $oldArray ) {
$newTask['task_id'] = $obj->task_id;
$newTask['title'] = $obj->title;
$newArray[$oldName][] = $newTask;
}
If you want to order it; you can just call a order function afterwards.
Related
I have an objectlist:
$deliveryOptions =
Array ( [0] => stdClass Object ( [item_id] => 55 [value] => delivery-online )
[1] => stdClass Object ( [item_id] => 55 [value] => delivery-campus )
[2] => stdClass Object ( [item_id] => 56 [value] => delivery-campus )
[3] => stdClass Object ( [item_id] => 81 [value] => delivery-blended )
)
I need to format it to an array:
$combined =
( [item_id] => 55 [course-delivery] => array( "delivery-online","delivery-campus")
( [item_id] => 56 [course-delivery] => delivery-campus )
( [item_id] => 81 [course-delivery] => delivery-blended )
My code so far:
foreach ($deliveryOptions as $row)
{
$temp = array('item_id'=>$row->item_id,
'course-delivery'=>$row->value
);
$course[] = $temp;
}
foreach ($course as $row)
{
$match = array_search($row['item_id'], array_column($combined, 'item_id'));
if(is_numeric($match))
{
$combined[$match]['course-delivery'][] = $row['course-delivery'];
}
else{
array_push($combined, [
'item_id' => $row['item_id'],
'course-delivery' => array($row['course-delivery'])
]);
}
}
The format of $combined might seem odd, but I have three different queries creating different object lists that all need to be combined into one JSON array based on 'item_id' as the key.
I have the part where all three get combined working, this new array configuration comes from a checkbox situation, thus the need to combine the different values off the same item_id.
No need for another foreach, you just create the structure along the way. First, initialize the container for the particular item_id.
When an item_id hits again and is not an array, just overwrite it, use the first value (string) and turn it to an array and finally push the value.
$deliveryOptions = [
(object) ['item_id' => 55, 'value' => 'delivery-online'],
(object) ['item_id' => 55, 'value' => 'delivery-campus'],
(object) ['item_id' => 56, 'value' => 'delivery-campus'],
(object) ['item_id' => 81, 'value' => 'delivery-blended'],
];
$combined = [];
foreach ($deliveryOptions as $row) {
if (!isset($combined[$row->item_id])) { // initialize if it doesn't exist
$combined[$row->item_id] = (array) $row; continue;
}
if (!is_array($combined[$row->item_id]['value'])) { // if another occurence
$temp = $combined[$row->item_id]['value']; // get the string initial value
$combined[$row->item_id]['value'] = []; // turn it into an array
$combined[$row->item_id]['value'][] = $temp; // and reassign and push inside the array
}
$combined[$row->item_id]['value'][] = $row->value; // push the value in the array
}
// $combined = array_values($combined); // array key reindex if needed
Sample output
I am trying to put content of one array into the same array. Here I have an array $mclass with values such as
Array
(
[0] => stdClass Object
(
[room_id] => 1,3,5
[day] => 1
[class_teacher] => TEA-2014-2
[final_exam_date] => 2015-09-21
)
)
You can see I have room_id index with 1,3,5 value. Now, I want to explode the room_id and get duplicate of same array index data with change of room_id and push into the array. and finally delete the current array index such as [0]. Here I want the final result as.
Array
(
[0] => stdClass Object
(
[room_id] => 1
[day] => 1
[class_teacher] => TEA-2014-2
[final_exam_date] => 2015-09-21
)
[1] => stdClass Object
(
[room_id] => 3
[day] => 1
[class_teacher] => TEA-2014-2
[final_exam_date] => 2015-09-21
)
[2] => stdClass Object
(
[room_id] => 5
[day] => 1
[class_teacher] => TEA-2014-2
[final_exam_date] => 2015-09-21
)
)
Here is my code for the same:
if(count($mclass)>0)
{
foreach($mclass as $mclasskey=>$mclass_row)
{
/* Room ID Calculation */
if(isset($mclass[$mclasskey]))
{
$temp_room_id = explode(',',$mclass_row->room_id);
if(count($temp_room_id)>1)
{
foreach($temp_room_id as $trkey=>$tr)
{
if(!in_array($temp_room_id[$trkey], $morning_class_semester))
{
array_push($morning_class_semester,$temp_room_id[$trkey]);
}
}
if(count($morning_class_semester)>0)
{
foreach($morning_class_semester as $mcskey=>$mcs)
{
$index_count = count($new_test);
$test[$index_count] = $mclass[$mclasskey];
$test[$index_count]->room_id = $morning_class_semester[$mcskey];
array_push($new_test,$test[$index_count]);
}
unset($mclass[$mclasskey]);
}
}
}
}
}
The code below does what you're looking for using only arrays. So you'll have to change the array access operators to -> since you're accessing an object. I'd do so, but it would break the example, so I'll leave that up to you.
Code Explained:
Loop through array selecting each subarray (object in your case), explode on the $item('room_id') ... ($item->room_id in your case) ... and create sub arrays, via loop, from that using the data from the original using each key. Remove the original item (which has the combined room_ids) and combine the placeholder and original array.
<?php
//Establish some data to work with
$array = array(
array(
"room_id" => "1,3,5",
"day" => 1,
"class_teacher" => "TEA-2014-2",
"final_exam_date" => "2015-09-21",
));
foreach ($array as $key => $item) {
$placeholder = array();
$ids = explode(',',$item['room_id']);
if (count($ids) > 1) {
foreach ($ids as $id) {
$push = array(
'room_id' => $id,
'day' => $item['day'],
'class_teacher' => $item['class_teacher'],
'final_exam_date' => $item['final_exam_date']
);
array_push($placeholder, $push);
}
$array = array_merge($array, $placeholder);
unset($array[$key]);
}
}
var_dump($array);
?>
I cant quite get my data from an array, it just shows a blank list of 3 list items when I run my foreach loop.
When I print my array it looks like this ->
Array
(
[1] => Array
(
[id] => 10
[orderinfo] => Array
[userid] => 210
[date] => 2013-06-20 13:46:27
)
[2] => Array
(
[id] => 18
[orderinfo] => helo
[userid] => 210
[date] => 2013-06-20 15:04:58
)
[3] => Array
(
[id] => 19
[orderinfo] => {"order":[{"id":"2","name":"Basil Cress","qty":"1"},{"id":"4","name":"Sakura Mix","qty":"1"},{"id":"6","name":"Beetroot Shoots","qty":2},{"id":"28","name":"Celery","qty":2},{"id":"24","name":"Orange Capsicums","qty":"1"}]}
[userid] => 210
[date] => 2013-06-20 15:06:46
)
)
My code so far..
foreach ($orderdata as $item) {
$orderinfo = json_decode($item->orderinfo, true);
$orderitem[] = array(
'date' => $item->date,
'productname' => $orderinfo['name'],
'productqty' => $orderinfo['qty'],
);
}
echo "<pre>";
print_r($orderdata);
echo "</pre>";
?>
<?php foreach ($orderitem as $orderitems) { ?>
<li>
<?php echo $orderitems['date']; ?>
</li>
<?php }; ?>
Try to declare your array before the loop like this. Are you already doing this?
$orderitem = array();
foreach ($orderdata as $item) {
$orderinfo = json_decode($item->orderinfo, true);
$orderitem[] = array(
'date' => $item->date,
'productname' => $orderinfo['name'],
'productqty' => $orderinfo['qty'],
);
}
You can also try to populate your array differently, like this:
array_push($orderitem,array(
'date' => $item->date,
'productname' => $orderinfo['name'],
'productqty' => $orderinfo['qty'],
));
Look at the structure of the the JSON for $orderInfo. It is a nested array. So $orderInfo['name'] doesn't exist. You want $orderInfo[0]['name'] or some other numerical index to fill in the data.
This is an array of objects which gets decoded to an array of associative arrays. You need to travel one more level down to get the name.
[
{"id":"2","name":"Basil Cress","qty":"1"},
{"id":"4","name":"Sakura Mix","qty":"1"},
{"id":"6","name":"Beetroot Shoots","qty":2},
{"id":"28","name":"Celery","qty":2},
{"id":"24","name":"Orange Capsicums","qty":"1"}
]
Could it be just your css?? Background color with the same text color? I know it's silly but who knows...
Try a print_r($orderitem); just like you did with $orderdata
I am using an API and am using a few foreach loops to get to the stage that I am at right now. Please see code below with my comments and also the results that I am getting below that.
// get recent_games api data
$recent_games_data = $player->recent_games();
//start arrays for below
$matches = array();
$gameType = array();
$myData = array();
// using foreach loops to dig in to api data
foreach($recent_games_data['gameStatistics']['array'] as $key_match_data => $value_match_data) {
$matches[] = $value_match_data['statistics'];
}
foreach($matches as $key_match) {
$gameType[] = $key_match['array'];
}
foreach ($gameType as $keyz) {
$myData[] = $keyz;
}
The $mydata array outputs this data below.
Array
(
[0] => Array
(
[0] => Array
(
[statType] => TRUE_DAMAGE_DEALT_TO_CHARACTER
[dataVersion] => 0
[value] => 3351
[futureData] =>
)
[1] => Array
(
[statType] => ASSISTS
[dataVersion] => 0
[value] => 14
[futureData] =>
)
[2] => Array
(
[statType] => NUM_DEATHS
[dataVersion] => 0
[value] => 3
[futureData] =>
)
)
[1] => Array
(
[0] => Array
(
[statType] => TRUE_DAMAGE_DEALT_TO_CHARACTER
[dataVersion] => 0
[value] => 331
[futureData] =>
)
[1] => Array
(
[statType] => ASSISTS
[dataVersion] => 0
[value] => 4
[futureData] =>
)
[2] => Array
(
[statType] => NUM_DEATHS
[dataVersion] => 0
[value] => 7
[futureData] =>
)
)
Of course there is much more data but this is basically what I have now. The first array [0] is each match and the second array are the statistics for that match. What I want is how do I get the statistics of each match without hardcoding the match array number, for example below.
$myData[0][0]['statType']
Let me know if you need more info and thank you.
EDIT: sorry for to mention that as new statistics data gets added to the api, the index number changes. IE TRUE_DAMAGE_DEALT_TO_CHARACTER is [0] to begin with but then may change to [1] or [2] etc.
Consider implementing a class for your stats items after parsing through the data (independent of individual match information keys):
class Stat_Item {
function __construct($id, $info) {
$this->id = $id;
if(!empty($info['damage'])
$this->damage_dealt = $info['damage'];
if(!empty($info['assists']))
$this->assists = $info['assists'];
if(!empty($info['deaths']))
$this->deaths = $info['deaths'];
}
}
$parsed_items = array();
foreach($mydata as $match_id => $match) {
$info = array();
foreach($match as $data_point) {
switch($data_point['statType']) {
case TRUE_DAMAGE_DEALT_TO_CHARACTER:
$info['damage'] = $data_point['value'];
break;
case ASSISTS:
$info['assists'] = $data_point['value'];
break;
case NUM_DEATHS:
$info['deaths'] = $data_point['value'];
break;
}
$parsed_items[] = new Stat_Item($match, $info);
}
}
Other than looping through them all, I don't see any way for you to get a particular match without calling it by its index.
You don't need several foreach loops - you can add to all three arrays in a single one. Also, it looks like $gameType and $myData end up containing the same data.
foreach($recent_games_data['gameStatistics']['array'] as $key_match_data => $value_match_data) {
$matches[] = $value_match_data['statistics'];
$gameType[] = $value_match_data['statistics']['array'];
$myData[] = $value_match_data['statistics']['array'];
}
I don't really understand why you don't just put it into the same array so you can access it easily, though:
foreach($recent_games_data['gameStatistics']['array'] as $key_match_data => $value_match_data) {
$matches[] = array('statistics' => $value_match_data['statistics'], 'data' => $value_match_data['statistics']['array']);
}
So My problem is:
I want to create nested array from string as reference.
My String is "res[0]['links'][0]"
So I want to create array $res['0']['links']['0']
I tried:
$result = "res[0]['links'][0]";
$$result = array("id"=>'1',"class"=>'3');
$result = "res[0]['links'][1]";
$$result = array("id"=>'3',"class"=>'9');
when print_r($res)
I see:
<b>Notice</b>: Undefined variable: res in <b>/home/fanbase/domains/fanbase.sportbase.pl/public_html/index.php</b> on line <b>45</b>
I need to see:
Array
(
[0] => Array
(
[links] => Array
(
[0] => Array
(
[id] => 1
[class] => 3
)
)
)
[1] => Array
(
[links] => Array
(
[0] => Array
(
[id] => 3
[class] => 9
)
)
)
)
Thanks for any help.
So you have a description of an array structure, and something to fill it with. That's doable with something like:
function array_create(&$target, $desc, $fill) {
preg_match_all("/[^\[\]']+/", $desc, $uu);
// unoptimized, always uses strings
foreach ($uu[0] as $sub) {
if (! isset($target[$sub])) {
$target[$sub] = array();
}
$target = & $target[$sub];
}
$target = $fill;
}
array_create( $res, "[0]['links'][0]", array("id"=>'1',"class"=>'3') );
array_create( $res, "[0]['links'][1]", array("id"=>'3',"class"=>'9') );
Note how the array name itself is not part of the structure descriptor. But you could theoretically keep it. Instead call the array_create() function with a $tmp variable, and afterwards extract() it to achieve the desired effect:
array_create($tmp, "res[0][links][0]", array(1,2,3,4,5));
extract($tmp);
Another lazy solution would be to use str_parse after a loop combining the array description with the data array as URL-encoded string.
I have a very stupid way for this, you can try this :-)
Suppose your string is "res[0]['links'][0]" first append $ in this and then put in eval command and it will really rock you. Follow the following example
$tmp = '$'.'res[0]['links'][0]'.'= array()';
eval($tmp);
Now you can use your array $res
100% work around and :-)
`
$res = array();
$res[0]['links'][0] = array("id"=>'1',"class"=>'3');
$res[0]['links'][0] = array("id"=>'3',"class"=>'9');
print_r($res);
but read the comments first and learn about arrays first.
In addition to mario's answer, I used another function from php.net comments, together, to make input array (output from jquery form serializeArray) like this:
[2] => Array
(
[name] => apple[color]
[value] => red
)
[3] => Array
(
[name] => appleSeeds[27][genome]
[value] => 201
)
[4] => Array
(
[name] => appleSeeds[27][age]
[value] => 2 weeks
)
[5] => Array
(
[name] => apple[age]
[value] => 3 weeks
)
[6] => Array
(
[name] => appleSeeds[29][genome]
[value] => 103
)
[7] => Array
(
[name] => appleSeeds[29][age]
[value] => 2.2 weeks
)
into
Array
(
[apple] => Array
(
[color] => red
[age] => 3 weeks
)
[appleSeeds] => Array
(
[27] => Array
(
[genome] => 201
[age] => 2 weeks
)
[29] => Array
(
[genome] => 103
[age] => 2.2 weeks
)
)
)
This allowed to maintain numeric keys, without incremental appending of array_merge. So, I used sequence like this:
function MergeArrays($Arr1, $Arr2) {
foreach($Arr2 as $key => $Value) {
if(array_key_exists($key, $Arr1) && is_array($Value)) {
$Arr1[$key] = MergeArrays($Arr1[$key], $Arr2[$key]);
}
else { $Arr1[$key] = $Value; }
}
return $Arr1;
}
function array_create(&$target, $desc, $fill) {
preg_match_all("/[^\[\]']+/", $desc, $uu);
foreach ($uu[0] as $sub) {
if (! isset($target[$sub])) {
$target[$sub] = array();
}
$target = & $target[$sub];
}
$target = $fill;
}
$input = $_POST['formData'];
$result = array();
foreach ($input as $k => $v) {
$sub = array();
array_create($sub, $v['name'], $v['value']);
$result = MergeArrays($result, $sub);
}