PHP warning array to string conversion loop inside array key - php

<?php $student = array(
1 => array(
"firstname" => "first",
"name" => "first",
"group" => "grp01",
"score" => array(
"ASP" => 86,
"PHP" => 79,
"JAVA" => 72,
"HTML" => 96,
"JAVASCRIPT" => 98,
"VBNET" => 66
)
),
2 => array(
"firstname" => "second",
"name" => "second",
"group" => "grp01",
"score" => array(
"ASP" => 80,
"PHP" => 70,
"JAVA" => 71,
"HTML" => 92,
"JAVASCRIPT" => 90,
"VBNET" => 78
)
),
3 => array(
"firstname" => "third",
"name" => "third",
"group" => "grp02",
"score" => array(
"ASP" => 88,
"PHP" => 88,
"JAVA" => 89,
"HTML" => 96,
"JAVASCRIPT" => 98,
"VBNET" => 71
)
) ); ?>
<?php
foreach($student as $std) {
foreach($std as $key => $p){
echo $std[$key];
} } ?>
i am trying to print in echo each student with they average score but right now i am stuck i got a warning about array to string convertion can someone give me some hint how i am suppose to do my loop.

Use PHP-functions to calculate the average for every student, rounded to two digits:
foreach($student as $std) {
$avg = round(array_sum($std['score']) / count($std['score']), 2);
echo $std['name']. ": $avg <br />";
}
see it working: http://codepad.viper-7.com/RBINCd

You are iterating the wrong array, once inside each student you must iterate over the "score", if not you were trying to convert the score array to a string:
foreach($student as $std) {
foreach($std["score"] as $language => $score) {
echo $score;
}
}

The error you are getting comes when you try to echo the "score" portion of the array. As it is itself an array it cannot be echo'd out in this way.
You will need another loop to add up the scores, then get the average outside of it.
Something along the lines of:
foreach($student as $std) {
foreach($std as $key => $p){
if ( $key === 'score'){
$avg = 0;
foreach( $p as $score){
$avg += $score;
}
$avg = ($avg/size_of($p));
}
}
}

Related

Php find key for min value in 2D array

I have the following 2D array and I would like to get the key of the smalest value in the [0] column if done is equal to no
$graph= array(
"CityA" => array(
"0" => "1",
"1" => "CityC",
"done" => "no",
),
"CityB" => array(
"0" => "4",
"1" => "CityA",
"done" => "no",
),
"CityC" => array(
"0" => "5",
"1" => "CityA",
"done" => "no",
),
);
Try this,
$arr = array_map(function($v){return $v[0];}, $graph);
$key = array_keys($arr, min($arr));
Here you go.
$tes = min( array_column( $graph, 0 ) );
$key = array_search( $tes, array_column( $graph, 0 ) );
$array_keys = array_keys($graph);
echo $array_keys[$key];
You should perform all of your checks in a single pass through your array.
My snippet will provide the first qualifying (contains the lowest [0] value AND has a done value of no) row's key.
Code: (Demo)
$graph = [
"CityB" => ["0" => "1", "1" => "CityA", "done" => "no"],
"CityA" => ["0" => "1", "1" => "CityC", "done" => "no"],
"CityD" => ["0" => "1", "1" => "CityD", "done" => "yes"],
"CityC" => ["0" => "5", "1" => "CityA", "done" => "no"]
];
$result = [];
foreach ($graph as $key => $row) {
if ($row['done'] === 'no' && (!isset($result[$key]) || $row[0] < $result[$key])) {
$result[$key] = $row[0];
}
}
echo key($result) ?? 'No "done => no" rows';
Output:
CityB

How to add array if key value is same

Hi i having difficulty to trace an multi dimensional array.
[
0 => array:7 [
"date" => "2016-01-19"
"placement_id" => 1
"requests" => 18
"revenue" => 1
],
1 => array:7 [
"date" => "2016-01-19"
"placement_id" => 1
"requests" => 2
"revenue" => 0.2
]
];
if placement_id are same i want resulted array:
1 => array:7 [
"date" => "2016-01-19"
"placement_id" => 1
"requests" => 20
"revenue" => 1.2
]
The requirement is to produce an output array that has:
Items with the same 'placement_id' having the 'requests' and revenue summed.
The key of the entry in the output array will be be the 'placement_id'.
That means that the output array will be smaller that the input array.
I decided to use the array_reduce function. There is no special reason, foreach loops work fine. It isn't any more efficient. It is just different.
The important point about array_reduce is that the $carry (accumulator) can be an array...
Working example at Eval.in
The code:
$outArray = array();
$outArray = array_reduce($src,
function($carry, $item) { // accumulate values if possible
$carryKey = $item['placement_id']; // array key
if (isset($carry[$carryKey])) { // accumulate values
$carry[$carryKey]['requests'] += $item['requests'];
$carry[$carryKey]['revenue'] += $item['revenue'];
} else { // is new - add to the output...
$carry[$carryKey] = $item;
}
return $carry;
},
array() /* accumulator ($carry) is an internal variable */);
Output Array:
array (2) [
'1' => array (4) [
'date' => string (10) "2016-01-19"
'placement_id' => integer 1
'requests' => integer 20
'revenue' => float 1.2
]
'666' => array (4) [
'date' => string (10) "2016-04-01"
'placement_id' => integer 666
'requests' => integer 266
'revenue' => float 666.20000000000005
]
]
Test Data:
$src = array(
0 => array(
"date" => "2016-01-19",
"placement_id" => 1,
"requests" => 18,
"revenue" => 1,
),
1 => array(
"date" => "2016-04-01",
"placement_id" => 666,
"requests" => 266,
"revenue" => 666.2,
),
2 => array(
"date" => "2016-01-19",
"placement_id" => 1,
"requests" => 2,
"revenue" => 0.2,
),
);
Taking that $arr parameter is the array that you show, we could create a function like this to look for duplicates ids and aggregate them. The $output array will return the results.
public function checkArray($arr) {
$output = array();
$deleted = array();
foreach($arr as $key => $value){
if (!in_array($key, $deleted)) {
$entry = array();
$entry['date'] = $value['date'];
$entry['placement_id'] = $value['placement_id'];
$entry['requests'] = $value['requests'];
$entry['revenue'] = $value['revenue'];
foreach($arr as $key2 => $value2){
if($key != $key2 && $value['placement_id'] == $value2['placement_id']){
$entry['requests'] += $value2['requests'];
$entry['revenue'] += $value2['revenue'];
$deleted[] = $key2;
}
}
$output[] = $entry;
}
}
return $output;
}

Sorting array by value

I have this array:
array(
"tour_0" => 1446,
"tour_1" => 1471,
"date-from-1471" => "2014-08-07",
"date-to-1471" => "2014-08-15",
"tour_2" => 30,
"date-from-30" => 2014-08-01,
"date-to-30" => 2014-08-05,
"tour_3" => 10
)
Now, i need it to be sorted to this:
array(
"0" => array("ID" => 1446),
"1" => array("ID" => 1471, "from" => "2014-08-07", "to" => "2014-08-15"),
"2" => array("ID" => 30, "from" => "2014-08-07", "to" => "2014-08-15"),
"3" => array("ID" => 10),
)
How can i accomplish this thing?
I've tried all sorts of things but i can't seem to figure this one out...
Thank's and sorry about the title but i just don't know how to describe it.
How about this?
$ret = [];
foreach($inputArray as $key => $value) {
if (preg_match('/^tour_([0-9]+)/', $key)) {
$ret[$value] = ["ID" => $value];
}
if (preg_match('/date-from-([0-9]+)/', $key, $matches)) {
$ret[$matches[1]]["from"] = $value;
}
if (preg_match('/date-to-([0-9]+)/', $key, $matches)) {
$ret[$matches[1]]["to"] = $value;
}
}
print_r($ret);
/*
Array
(
"1446" => Array ("ID" => 1446),
"1471" => Array ("ID" => 1471, "from" => "2014-08-07", "to" => "2014-08-15"),
"30" => Array ("ID" => 30, "from" => "2014-08-01", "to" => "2014-08-05"),
"10" => Array ("ID" => 10)
)*/
Close enough? (it is quite trival change the keys of the array, considering they are in order (0, 1, 2, 3, ...), if they are not, maybe you can save the order also (in another item of the subarray) and recompose again once this array is formed)

Put array elements with specific value to end of array

I have a multidimensional array like that:
$array = array(
1 => array(
"name" => 'Jon',
"year" => '2012'
),
2 => array(
"name" => 'Jack',
"year" => '1900'
),
3 => array(
"name" => 'Lisa',
"year" => '1900'
),
4 => array(
"name" => 'Ygritte',
"year" => '1929'
),
);
All the items that have a year of '1900' should be put to the end of the array. What is a lightweight solution?
Desired result:
$array = array(
1 => array(
"name" => 'Jon',
"year" => '2012'
),
2 => array(
"name" => 'Ygritte',
"year" => '1929'
),
3 => array(
"name" => 'Jack',
"year" => '1900'
),
4 => array(
"name" => 'Lisa',
"year" => '1900'
),
);
I assume you don't care about your indexes because you rearrange them. First thing, you should probably start indexes in your array from 0 and not for 1.
You can use the following code:
$array = array(
1 => array(
"name" => 'Jon',
"year" => '2012'
),
2 => array(
"name" => 'Jack',
"year" => '1900'
),
3 => array(
"name" => 'Lisa',
"year" => '1900'
),
4 => array(
"name" => 'Ygritte',
"year" => '1929'
),
);
$array = array_values($array);
for ($i=0, $c = count($array); $i<$c; ++$i) {
if ($array[$i]['year'] == '1900') {
$array[] = $array[$i];
unset($array[$i]);
}
}
$array = array_values($array);
foreach ($array as $k => $v) {
echo $k.' '.$v['name'].' '.$v['year']."<br />";
}
Result for this is:
0 Jon 2012
1 Ygritte 1929
2 Jack 1900
3 Lisa 1900
Of course if you want, you can change your keys adding 1 to each one (starting from the last element) so you have the same output as in question but I assume this one is enough for you.
The simplest approach could be something like this:
Find the element that has year 1900 (iterating the loop) then,
For example working for index 3
$tmp = $myArray['3'];
unset($myArray['3'];
$myArray['3'] = $tmp;
$tmp is a temporary variable inside the loop.
Try using SplHeap
class MyQueue extends SplHeap
{
public function compare($item1, $item2)
{
if ($item1['year'] === $item2['year']) return 0;
return ($item1['year'] == 1900) ? -1 : 0;
}
}
$queue = new MyQueue();
foreach ($array as $item) {
$queue->insert($item);
}
$queue->top();
$array = array();
while($queue->valid()){
$array[] = $queue->current();
$queue->next();
}
print_r($array);
Hope this following code will help you:
function aasort (&$array, $key) {
$sorter=array();
$ret=array();
reset($array);
foreach ($array as $ii => $va) {
$sorter[$ii]=$va[$key];
}
rsort($sorter);
foreach ($sorter as $ii => $va) {
$ret[$ii]=$array[$ii];
}
$array=$ret;
}
aasort($array,"year");
print_r($array);

Put nested array into one array

Suppose i have a array like this :
Array(
'1' => Array(
"ID" => 1,
"Name" => "name 1"
),
'2' => Array (
Array(
"ID" => 2,
"Name" => "name 2"
)
),
'3' => Array(
Array(
Array(
Array(
"ID" => 3,
"Name" => "name3"
)
)
),
'4' => Array (
Array {
"ID" => 4,
"Name" => "name 4"
),
Array(
"ID" => 5,
"Name" => "name 5"
),
Array(
"ID" => 6,
"Name" => "name 6"
)
);
number of sub-arrays is not ordered it may be 3, 4 or 5 etc...
and i wanted to get :
Array(
Array( "ID" => 1, "Name" => "name 1"),
Array( "ID" => 2, "Name" => "name 2"),
Array( "ID" => 3, "Name" => "name 3"),
Array( "ID" => 4, "Name" => "name 4"),
Array( "ID" => 5, "Name" => "name 5"),
Array( "ID" => 6, "Name" => "name 6"));
Is there an easy way to do this ?
EDIT :
Edited the above array to add :
'4' => Array (
Array {
"ID" => 4,
"Name" => "name 4"
),
Array(
"ID" => 5,
"Name" => "name 5"
),
Array(
"ID" => 6,
"Name" => "name 6"
)
);
which aren't nested but i still want them to be in my final array.
Thanks.
//Assuming your data is in $in
$out=array();
foreach($in as $k=>$v) {
while ((is_array($v)) && (isset($v[0]))) $v=$v[0];
//See below for next line
$out[]=$v;
}
print_r($out);
With the marked line being either $out[$k]=$v; or $out[]=$v; depending on wether you want to keep the 1st-level keys. In your desired output you do not ,so use the shown version
Edit
With you changed input array, you need to do something like
function addtoarray($inarray, &$outarray) {
foreach ($inarray as $i) {
if (!is_array($i)) continue;
if (isset($i['ID'])) $outarray[]=$i;
else addtoarray($i,$outarray);
}
}
$out=array();
addtoarray($in,$out);
print_r($out);
This was tested against your new input data
You could recurse through the array and check for the ID field.
function combine_array(array $src, array &$dest)
{
if( isset( $src['ID'] ) ) {
$dest[] = $src;
return;
}
foreach( $sub in $src ) {
combine_array( $sub, $dest );
}
}
Just wrote this off the top of my head, no testing, so it might have a few problems. But that's the basic idea.
This may work for you, assuming $array is the variable and php 5.3
//process
$array = array_map(function($block) {
$return = '';
foreach ($block as $sub) {
if (true === isset($sub['ID']) {
$return = $block;
break;
}
}
return $block;
}, $array);
array_filter($array); //remove empty elements
Wrote up a quick recursive function. You'll need to write any appropriate error handling and check the logic, since a discrepancy in your data could easily turn this into an infinite loop:
$output = array();
foreach ( $data as $d ) {
$output[] = loop_data( $d );
}
function loop_data( $data ) {
// Check if this is the right array
if( ! array_key_exists( "ID", $data ) ) {
// Go deeper
$data = loop_data( $data[0] );
}
return $data;
}

Categories