JSON - Display only certain data in php - php

This is my json data as an array, and it is in the file data.json, I tried to parse the data using php, but I am not able show the result using a for loop.
array (
'data' =>
array (
0 =>
array (
'a' => 3222,
'b' => 3,
),
1 =>
array (
'a' => 3221,
'b' => 3,
),
2 =>
array (
'a' => 2215,
'b' => 2,
),
3 =>
array (
'a' => 2214,
'b' => 2,
),
4 =>
array (
'a' => 3218,
'b' => 2,
),
5 =>
array (
'a' => 3217,
'b' => 3,
),
6 =>
array (
'a' => 3216,
'b' => 3,
),
7 =>
array (
'a' => 1235,
'b' => 1,
),
8 =>
array (
'a' => 1234,
'b' => 1,
),
9 =>
array (
'a' => 1233,
'b' => 1,
),
10 =>
array (
'a' => 3213,
'b' => 3,
)
)
I want to display only the data, which is "b=3" which contains the maximum value of "a".
Here is my code, which displays all the results of "a" as a string. All the data is shown as a list.
<?php
$json = file_get_contents('data.json');
$data = json_decode($json,true);
$q = $data['data'];
$length = count($q);
for ($i = 0; $i<$length ; $i++){
if ($q[$i]['b']==3){
$pc = $q[$i]['a'];
echo $pc;
echo "<br>";
}
}
This is not the result I was expected.

One way to solve this could be to check the current value of $pc against the latest value;
If that is higher, then overwrite it:
$q = $data['data'];
$length = count($q);
$max = 0;
for ($i = 0; $i<$length ; $i++){
if ($q[$i]['b']==3){
$pc = $q[$i]['a'];
if ($pc > $max) {
$max = $pc;
}
}
}
echo $max; //3222
Another option could be to use array_map and max:
$result = max(array_map(function($x){
if($x['b'] === 3) return $x['a'];
}, $q
));
echo $result; //3222

Related

Order rows by their column value to create repeating sequences of ascending values [duplicate]

This question already has answers here:
Sort a flat array in recurring ascending sequences
(5 answers)
Closed 5 months ago.
I want to order my associative rows by their column value as sequences of ascending values.
Sample array1:
$args = [
'a' => ['zebra' => 1],
'b' => ['zebra' => 0],
'c' => ['zebra' => 0],
'd' => ['zebra' => 0],
'e' => ['zebra' => 1],
];
Desired result:
[
'b' => ['zebra' => 0],
'a' => ['zebra' => 1],
'c' => ['zebra' => 0],
'e' => ['zebra' => 1],
'd' => ['zebra' => 0],
]
Notice that duplicate values are not consecutive while sorting ascending. Instead, all unique, first-encountered values come first, then second encountered values, etc.
Sample array2:
$args = [
'a' => ['zebra' => 1],
'b' => ['zebra' => 1],
'c' => ['zebra' => 1],
'd' => ['zebra' => 1],
'e' => ['zebra' => 0],
'f' => ['zebra' => 0],
];
Desired result:
[
'e' => ['zebra' => 0],
'a' => ['zebra' => 1],
'f' => ['zebra' => 0],
'b' => ['zebra' => 1],
'c' => ['zebra' => 1],
'd' => ['zebra' => 1],
]
Edit: I tried to do this with usort, via this similar, but different, question, and the answer was no, so I am looking for a programatic solution (without usort).
Same idea to split the input into the 1's and 0's, then output a 0 and a 1 as long as there is something left to output. As each time you output a value, the array is reduced, this just continues till both lists are empty so should cope with unbalanced lists...
$temp = [ 0 => [], 1 => []];
foreach($args as $key=>$value){
$temp[$value['zebra']][] = $key;
}
$output = [];
while ( !empty($temp[0]) || !empty($temp[1]) ) {
if ( !empty($temp[0]) ) {
$next = array_shift($temp[0]);
$output [$next] = $args[$next];
}
if ( !empty($temp[1]) ) {
$next = array_shift($temp[1]);
$output [$next] = $args[$next];
}
}
I can suggest you to use deconstruction with count of comparison.
At first step you can collect all indexes with zebra = 1 and with zebra = 0:
$zeros = [];
$ones = [];
foreach($args as $let=>$arg){
if ($arg['zebra'] === 1) {
$ones[] = $let;
} else if ($arg['zebra'] === 0) {
$zeros[] = $let;
}
}
And now you can construct resultant array like:
if(abs(count($zeros) - count($ones)) === 1) { // if their difference equal to 1
if (count($ones) > count($zeros)){ // if $ones is bigger
foreach($zeros as $ind=>$let){
$res[$ones[$ind]] = ['zebra' => 1];
$res[$let] = ['zebra' => 0];
$tmp = $ind;
}
$res[$ones[$tmp+1]] = ['zebra' => 1];
} else if (count($ones) < count($zeros)){ // if $zeros is bigger
foreach($ones as $ind=>$let){
$res[$zeros[$ind]] = ['zebra' => 0];
$res[$let] = ['zebra' => 1];
$tmp = $ind;
}
$res[$zeros[$tmp+1]] = ['zebra' => 0];
}
}
Output:
Array
(
[b] => Array
(
[zebra] => 0
)
[a] => Array
(
[zebra] => 1
)
[c] => Array
(
[zebra] => 0
)
[e] => Array
(
[zebra] => 1
)
[d] => Array
(
[zebra] => 0
)
)
Demo
If you need result in case of (1,0,1,0,0) use next constructor:
if (count($ones) > count($zeros)){
foreach($ones as $ind=>$let){
if (isset($zeros[$ind])) $res[$zeros[$ind]] = ['zebra' => 0];
$res[$let] = ['zebra' => 1];
}
} else if (count($zeros) > count($ones)){
foreach($zeros as $ind=>$let){
$res[$let] = ['zebra' => 0];
if (isset($ones[$ind])) $res[$ones[$ind]] = ['zebra' => 1];
}
}
Output:
Array
(
[b] => Array
(
[zebra] => 0
)
[a] => Array
(
[zebra] => 1
)
[d] => Array
(
[zebra] => 0
)
[c] => Array
(
[zebra] => 1
)
[e] => Array
(
[zebra] => 0
)
)
Demo
Here's a solution using array_map after grabbing 1s and 0s in separate arrays:
$args0 = array_filter($args, function ($arg) {
return $arg['zebra'] === 0;
});
$args1 = array_filter($args, function ($arg) {
return $arg['zebra'] === 1;
});
$result = array_merge(...array_map(static function ($arg0Key, $arg1Key) use ($args0, $args1) {
if ($arg0Key !== null) {
$result[$arg0Key] = $args0[$arg0Key];
}
if ($arg1Key !== null) {
$result[$arg1Key] = $args1[$arg1Key];
}
return $result;
}, array_keys($args0), array_keys($args1)));
print_r($result);
Demo: https://3v4l.org/sfqeq
Note: using two array_filter to separate values looks nice but loops over $args twice; prefer a simple loop if the initial array can be somewhat big. This is not the relevant part of the answer, though.

How to sum same array in php [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 8 years ago.
Improve this question
I want to sum array in same key and different value.
Array
(
0 => Array
(
'locker_id' => 3,
'locker_model' => 1,
'qty' => 2
),
1 => Array
(
'locker_id' => 3,
'locker_model' => 1,
'qty' => 1
),
2 => Array
(
'locker_id' => 2,
'locker_model' => 1,
'qty' => 2
),
3 => Array
(
'locker_id' => 3,
'locker_model' => 1,
'qty' => 2
),
4 => Array
(
'locker_id' => 2,
'locker_model' => 1,
'qty' => 2
)
);
I want Output it
Array
(
0 => Array
(
'locker_id' => 3,
'locker_model' => 1,
'qty' => 5
),
1 => Array
(
'locker_id' => 2,
'locker_model' => 1,
'qty' => 4
)
);
Thanks.
You could browse your array while creating a new one with keys like "locker_id-locker_model", then you can easily check if your locker exists in this array with array_key_exists function.
$inputArray = array( ... ); // this is your message array
$outputArray = array();
foreach( $inputArray as $locker )
{
if( !array_key_exists( $locker["locker_id"]."-".$locker["locker_model"], $outputArray ) )
{
$outputArray[ $locker["locker_id"]."-".$locker["locker_model"] ] = array(
"locker_id" => $locker["locker_id"],
"locker_model" => $locker["locker_model"],
"qty" => 0
);
}
$outputArray[ $locker["locker_id"]."-".$locker["locker_model"] ]["qty"]++;
}
var_dump( $outputArray );
$dataArr = array
(
0 => array
(
'locker_id' => 3,
'locker_model' => 1,
'qty' => 2
),
1 => array
(
'locker_id' => 3,
'locker_model' => 1,
'qty' => 1
),
2 => array
(
'locker_id' => 2,
'locker_model' => 1,
'qty' => 2
),
3 => array
(
'locker_id' => 3,
'locker_model' => 1,
'qty' => 2
),
4 => array
(
'locker_id' => 2,
'locker_model' => 1,
'qty' => 2
)
);
$sumArr = array();
if(count($dataArr)>0){
foreach($dataArr as $data){
if(!isset($sumArr[$data['locker_id']])){
$sumArr[$data['locker_id']] = $data;
}
$sumArr[$data['locker_id']]['qty'] +=$data['qty'];
}
}
echo "<pre>";print_r($sumArr);
Considering $array1 is your first array,
$array2 = array();
foreach($array1 as $k=>$v) {
if(!isset($array2[$v['locker_id']])) {
$array2[$v['locker_id']] = $v;
} else {
$array2[$v['locker_id']]['qty'] += $v['qty'];
}
}
print_r($array2);
Try this
$arr is your array
$j = 0;
$new = array();
$new[0][qty];
for($i=0;$i<arraylength;$i++){
foreach($arr as $key => $value) {
if($arr[$i][lockerid] == $arr[$key][lockerid]) {
$new[$j][lockerid] = $arr[$key][lockerid];
$new[$j][lockermodel] = $arr[$key][lockermodel];
$new[$j][qty] = $new[$i][qty] + $arr[$key][qty];
J++;
}
}
}
$result = array();
foreach($array as $key => $value){
if(isset($value['locker_id'])){
$result[$value['locker_id']]['qty'] += $value['qty'];
}
else{
$result[$value['locker_id']] = $value;
}
}
You have to loop over your array and save it to another let's say $result. In $result you should put the locker_id as key and then you only have to verify if that key exists. If it is you add the qty value, if isn't you have to add the entire new item.
try this
$ARR_OUTPUT = array();
// $arr will contains your input array
foreach($arr as $arr_val)
{
$locker_id = $arr_val['locker_id'];
$locker_model = $arr_val['locker_id'];
$qty = $arr_val['locker_id'];
if(isset($ARR_OUTPUT[$locker_id][$locker_model]))
{
$ARR_OUTPUT[$locker_id][$locker_model] += $qty;
}
else
{
$ARR_OUTPUT[$locker_id][$locker_model] = $qty;
}
}
echo "<pre>";
print_r($ARR_OUTPUT);
$ARR_OUTPUT2 = array();
foreach($ARR_OUTPUT as $locker_id=>$arr_values)
{
foreach($arr_values as $locker_model=>$qty)
{
$arr_temp['locker_id'] = $locker_id;
$arr_temp['locker_model'] = $locker_model;
$arr_temp['qty'] = $qty;
$ARR_OUTPUT2[] = $arr_temp;
}
}
echo "<pre>";
print_r($ARR_OUTPUT2);

Cannot modify multidimensional array PHP

I have two arrays.
First one ($dcel) looks like this:
Array(
[1] => Array
(
[V1] => 5
[V2] => 2
[F1] => 4
[F2] => 1
[P1] => 7
[P2] => 4
)
etc..
Second one ($PctOldNew) looks like this:
Array(
[0] => Array
(
[old] => 1
[new] => 3
)
etc..
I'm trying to find the 'old' values (which are the initial) in the first array. Here's my code:
foreach ($dcel as $latura) {
for($i = 0; $i <= $nrPct; $i++){
if($PctOldNew[$i]['old'] == $latura[V1]){
$latura[V1] = $PctOldNew[$i]['new'];
}
}
}
If I output the $PctOldNew inside if statment, the output it's the correct answer, but if i try to modify $latura[V1] the $dcel remains untouched.
I've tried with reference, keys... but nothing works and i can't see what's wrong.
This works:
edit: adding a 2nd array element to $dcel to show how it works
<?php
$dcel = Array(
'1' => Array
(
'V1' => 1, // <-- note that i changed this value from your original '5' to '1' so that your condition will actually match something, since this example data set doesn't actually have something to match
'V2' => 2,
'F1' => 4,
'F2' => 1,
'P1' => 7,
'P2' => 4
)
'2' => Array
(
'V1' => 5,
'V2' => 2,
'F1' => 4,
'F2' => 1,
'P1' => 7,
'P2' => 4
)
);
$PctOldNew = Array(
'0' => Array
(
'old' => 1,
'new' => 3
)
);
foreach ($dcel as &$latura) { // <-- reference on &$latura
for($i = 0; $i <= $nrPct; $i++){
if($PctOldNew[$i]['old'] == $latura['V1']){
$latura['V1'] = $PctOldNew[$i]['new'];
}
}
}
echo "<pre>";print_r($dcel);
output
Array
(
[1] => Array
(
[V1] => 3
[V2] => 2
[F1] => 4
[F2] => 1
[P1] => 7
[P2] => 4
)
[2] => Array
(
[V1] => 5
[V2] => 2
[F1] => 4
[F2] => 1
[P1] => 7
[P2] => 4
)
)
#CrayonViolent it didn't work, i tried so many times.
I was playing right now with the code and it seems that like this it's working:
foreach ($dcel as $key => $value) {
foreach ($value as $val) {
for($i = 0; $i <= $nrPct; $i++){
if($PctOldNew[$i]['old'] == $value[V1])
$new = $PctOldNew[$i]['new'];
}
$val = $new;
}
$dcel[$key][V1] = $val;
}
...but i don't know why.
The most convenient way in your case would be using array_map() function
Like this:
$array = array(1,2,3,4,5);
$replacements = array(
array('old'=>1, 'new'=>11),
array('old'=>3, 'new'=>33),
);
$array = array_map(function($element){
global $replacements;
foreach($replacements as $r) if($r['old']==$element) return $r['new'];
return $element;
}, $array);
print_r($array);
Result:
Array ( 11, 2, 33, 4, 5 )
Another weird way is to use array_walk
array_walk(&$dcel, function($latura){
for($i = 0; $i <= $nrPct; $i++){
if($PctOldNew[$i]['old'] == $latura[V1]){
$latura[V1] = $PctOldNew[$i]['new'];
}
}
});
Or array_map
$dcel = array_map(function($latura){
for($i = 0; $i <= $nrPct; $i++){
if($PctOldNew[$i]['old'] == $latura[V1]){
$latura[V1] = $PctOldNew[$i]['new'];
}
}
return $latura;
}, $dcel);
(Not sure why array_walk and array_map have reversed parameter position)
Updated with the real reason and 2 more possible solutions
The reason you can't modify $latura is because you are using for...each loop which will pass $latura by-value rather than by-reference. Based on this reason, you have 2 more solutions,
Use for $dcel as $key => $latura then you can change $dcel[$key]
Use for $dcel as &$latura then you can change the item directly

Creating not-so-random list from given array in PHP

I need to generate list of n ($size_of_list) names...
Possible members are given in array ($names_list) which gives name and chances of appearance of that name. So it is an array of 40 arrays of string and integer:
$names_list = array (
0 => array ('name' => "Mike", 'frequency' => 8),
1 => array ('name' => "Jane", 'frequency' => 7),
2 => array ('name' => "Leopold", 'frequency' => 1),
3 => array ('name' => "George", 'frequency' => 5),
...
39 => array ('name' => "Mark", 'frequency' => 6)
)
$names_list[0] = array('name' => "Mike", 'frequency' => 8) means that $name="Mike" has $frequency (or chance) of 8, and "Leopold" has chance value 1 - small chance to appear...
Specify $size_of_list and check out $result in the end. This uses random depending on weight.
$result = array();
$total = 0;
foreach ($names_list as $row) {
$total += $row['frequency'];
}
$max = mt_getrandmax();
$pre_sum = $total / $max;
for ($i = 0; $i < $size_of_list; ++$i) {
$sum = $pre_sum * mt_rand(0, $max); // $sum = $total * (mt_rand(0, $max)/$max);
foreach ($names_list as $row) {
if (($sum -= $row['frequency']) < 0) {
$result[] = $row['name'];
break;
}
}
}
var_dump($result);
My idea is to expand array with new value 'rnd' which represents sum of $frequency and previous elements rnd (where first element 'rnd' is first element's 'frequency')
$names_list[0]['rnd'] = $names_list[0]['frequency'];
for ($i=1; $i<count($names_list); $i++)
$names_list[$i]['rnd'] = $names_list[$i]['frequency'] + $names_list [$i-1]['rnd'];
and expanded array would look like this:
$names_list = array (
0 => array ('name' => "Mike", 'frequency' => 8, 'rnd' => 8),
1 => array ('name' => "Jane", 'frequency' => 7, 'rnd' => 15),
2 => array ('name' => "Leopold", 'frequency' => 1, 'rnd' => 16),
3 => array ('name' => "George", 'frequency' => 5, 'rnd' => 21),
//... other elements
39 => array ('name' => "Mark", 'frequency' => 8, 'rnd' => $sum_of_all_frequencies)
)
And then set $rand_max to value of last elements 'rnd', and then to create finale list by
comparing $random and all 'rnd' values...
$rand_max = $names_list[count($names_list)-1]['rnd'];
for ($i=1; $i<$size_of_list; $i++)
{
$random = rand (1, $rand_max);
$result = $names_list[0]['name'];
foreach ($names_list as $key => $val)
if ( ($random) > ($val['rnd']) )
$result = $names_list[$key+1]['name'];
$list[$i] = $result;
}
This solution works, but i think there are better (smarter) ways...
I would appreciate any help/suggestion...

Counting values within multidimensional arrays?

I have a large array where I basically need to count the number of uniques:
example array
The end result I am looking for something like
$result = array(
'A3D5' => array('P2' => 1, 'P3' => 1, 'P4' => 1, 'total' => 3),
'AE5S' => array('P4' => 1, 'total' => 1)
);
I've tried foreaching through but can't seem to figure out how to sort them into another key, something like $zone = "P{$array['zone']}"; $result[$zone][$prestige]++ or seems to kind of not work or just error.
$array = array(
"denizen" => array
(
"prestige" => 2,
"zone" => "A3D5",
"scope_frag" => 765
),
"생각" => array
(
"prestige" => 4,
"zone" => "A3D5",
"scope_frag" => 135
),
"Ryans" => array
(
"prestige" => 3,
"zone" => "A3D5",
"scope_frag" => 78
),
"지적인" => array
(
"prestige" => 2,
"zone" => "AE5S",
"scope_frag" => 481
)
);
foreach ($array as $group) {
$zones[$group["zone"]][] = $group["prestige"];
}
foreach ($zones as $name => $zone) {
$total = count($zone);
foreach ($zone as $prestige) {
$result[$name]["P".$prestige] += 1;
}
ksort($result[$name]);
$result[$name]["total"] = $total;
}
echo "<pre>";
print_r($result);
echo "</pre>";

Categories