Sorting multiarray on numeric field - php

I have an array like below. I need to sort each array on the 2 key.
myarray [
[2020] = [0 => 123, 1 => 234, 2 => 45],
[2021] = [0 => 123, 1 => 34, 2 => 345],
[2019] = [0 => 123, 1 => 134, 2 => 645]
]
So the results would be
[2020] =
45
123
234
[2021] =
34
123
345
[2019] =
123
134
645]
I've tried
array_multisort( array_column($myarray, $myarray[2]), SORT_ASC, $myarray );
and
usort($myarray, array($myarray[2], 'sort_function'));
function sort_function($a, $b)
{
if ($a == $b) {
return 0;
}
return ($a < $b) ? -1 : 1;
}
Neither of the above worked. Would someone please point out my mistake or the correct way to do this?
Here is a better explanation of the problem:
myarray [
[2020] = [0 => 123, 1 => 234, 2 => 357],
[2020] = [0 => 123, 1 => 34, 2 => 157],
[2020] = [0 => 123, 1 => 134, 2 => 257]
]
[2020] =
157
257
357

For your second result, use:
$second_elements = array_column($myarray, 2);
sort($second_elements);

Related

PHP multidimensional array sort by value

Regarding this multidimensional array:
[
(int) 7 => [
(int) 0 => [
(int) 0 => '12:45',
(int) 1 => 'E1',
(int) 2 => 'B EXTREME 30'
],
(int) 1 => [
(int) 0 => '10:15',
(int) 1 => 'E1',
(int) 2 => 'B SHAPE 30'
],
],
(int) 1 => [
(int) 0 => [
(int) 0 => '09:30',
(int) 1 => 'E2',
(int) 2 => 'CYCLING VIRTUAL 50'
],
(int) 1 => [
(int) 0 => '10:30',
(int) 1 => 'E1',
(int) 2 => 'BODY PUMP VIRTUAL 60'
],
(int) 2 => [
(int) 0 => '11:45',
(int) 1 => 'E1',
(int) 2 => 'BODY BALANCE VIRTUAL 60'
],
],
(int) 2 => [
(int) 0 => [
(int) 0 => '14:45',
(int) 1 => 'E2',
(int) 2 => 'CYCLING VIRTUAL 50'
],
(int) 1 => [
(int) 0 => '17:00',
(int) 1 => 'E1',
(int) 2 => 'POSTURA ALONGAMENTO 60'
],
(int) 2 => [
(int) 0 => '09:15',
(int) 1 => 'E1',
(int) 2 => 'BODY PUMP 50'
],
]
]
The first key, of each first level array, are days of the week (day 7, day 1 and day 2).
The arrays inside each first level array contain hour (09:45), rooms (E1) and description (B EXTREME 30).
I tried to sort this multidimensional array by the second levels array hour value.
I used usort(), ksort(), array_multisort(), and some custom made functions for sorting the array as i need without luck.
The inside arrays must be sorted by ascending order, like this (example with day 2):
09:15 -> 14:45 -> 17:00
Does anyone knows how can i achieve this?
Assuming your data is called $data. Iterate the outer array, and apply a sort on each mid-level array, based on the time-part (in the innermost arrays). As your times are always formatted as "hh:ss", a string comparison in the usort callback does the job:
foreach ($data as &$events) {
usort($events, function($a, $b) {
return strcmp($a[0], $b[0]);
});
}
Note the & in the foreach: this makes sure you sort the original data, and not a copy of it.
If you want to create a new array, let's say $result, then do this (no & here!):
foreach ($data as $day => $events) {
usort($events, function($a, $b) {
return strcmp($a[0], $b[0]);
});
$result[$day] = $events;
}
usort — Sort an array by values using a user-defined comparison function.
Lets create a function where we compare time of two events.
This is part of your array
$array = [
2 => [
0 => [
0 => '14:45',
1 => 'E2',
2 => 'CYCLING VIRTUAL 50'
],
1 => [
0 => '17:00',
1 => 'E1',
2 => 'BODY PUMP VIRTUAL 60'
],
2 => [
0 => '09:15',
1 => 'E1',
2 => 'BODY BALANCE VIRTUAL 60'
],
],
];
This is an example how to sort items for one day (day 2)
usort($array[2], function ($a, $b) {
$time_a = strtotime($a[0]); // convert string to a unix timestamp to compare int
$time_b = strtotime($b[0]);
return $time_a - $time_b;
});
Output using print_r($array);
Array
(
[2] => Array
(
[0] => Array
(
[0] => 09:15
[1] => E1
[2] => BODY BALANCE VIRTUAL 60
)
[1] => Array
(
[0] => 14:45
[1] => E2
[2] => CYCLING VIRTUAL 50
)
[2] => Array
(
[0] => 17:00
[1] => E1
[2] => BODY PUMP VIRTUAL 60
)
)
)
To sort all days we do in a loop, passing each day array as a reference using &:
foreach ($array as &$day) {
usort($day, function ($a, $b) {
$time_a = strtotime($a[0]);
$time_b = strtotime($b[0]);
return $time_a - $time_b;
});
}

foreach loop in array value in only last value print

I have get foreach loop in month and total month value count data in array print but only last value print in array
foreach($rawData as $Data)
{
$monthsss = $Data['month_no'];
if($monthsss=='1')
{
$arrayF['jan'] = $Data['month_count'];
}
else
{
$arrayF['jan'] = '0';
}
if($monthsss=='2')
{
$arrayF['feb'] = $Data['month_count'];
}
else
{
$arrayF['feb'] = '0';
}
}
When someone comments and asks Please show input and expected output. this is not done to give you more work, but there are many ways to achieve what you want but many answers can be wrong or require much more code (as with the accepted answer).
Presuming this is your data:
$rawData = [
['month_no' => 1, 'month_count' => 1],
['month_no' => 2, 'month_count' => 1],
['month_no' => 3, 'month_count' => 1],
['month_no' => 4, 'month_count' => 1],
['month_no' => 1, 'month_count' => 2],
['month_no' => 6, 'month_count' => 2],
['month_no' => 7, 'month_count' => 6],
['month_no' => 12, 'month_count' => 4],
];
Do you want just the summed up values?
<?php
$array = [];
foreach ($rawData as $data) {
$m = strtolower(DateTime::createFromFormat('!m', $data['month_no'])->format('M'));
$array[$m] = !isset($array[$m]) ? $data['month_count'] : $array[$m]+$data['month_count'];
}
print_r($array);
https://3v4l.org/vXgCL
Array
(
[jan] => 3
[feb] => 1
[mar] => 1
[apr] => 1
[jun] => 2
[jul] => 6
[dec] => 4
)
Or do you want an array of all the months with the summed up values:
<?php
$array = [];
foreach (range(1, 12) as $month) {
$m = strtolower(DateTime::createFromFormat('!m', $month)->format('M'));
$monthSet = array_filter($rawData, function ($v) use ($month) {
return $v['month_no'] === $month;
});
$array[$m] = 0;
foreach ($monthSet as $data) {
$array[$m] += $data['month_count'];
}
}
print_r($array);
https://3v4l.org/vqnnv
Array
(
[jan] => 3
[feb] => 1
[mar] => 1
[apr] => 1
[may] => 0
[jun] => 2
[jul] => 6
[aug] => 0
[sep] => 0
[oct] => 0
[nov] => 0
[dec] => 4
)
Or perhaps don't even care about the month's strings as your comment suggests.
<?php
$array = [];
foreach ($rawData as $data) {
$m = $data['month_no'];
$array[$m] = !isset($array[$m]) ? $data['month_count'] : $array[$m]+$data['month_count'];
}
print_r($array);
https://3v4l.org/7gKRo
Array
(
[1] => 3
[2] => 1
[3] => 1
[4] => 1
[6] => 2
[7] => 6
[12] => 4
)
Its why we ask..
Please modify your code as follows
foreach($rawData as $Data)
{
$monthsss = $Data['month_no'];
if($monthsss=='1')
{
$arrayF['jan'] = is_null($Data['month_count'])? 0 : $Data['month_count'];
}
if($monthsss=='2')
{
$arrayF['feb'] = is_null($Data['month_count'])? 0 : $Data['month_count'];
}
}

Get previous and next array by key from array object

i have array object and want get 2 previous and and 2 next array group by specific key.
Array
(
[467] => stdClass Object
(
[id] => 467
[user_id] => 1
)
[468] => stdClass Object
(
[id] => 468
[user_id] => 1
)
[469] => stdClass Object
(
[id] => 469
[user_id] => 1
)
[474] => stdClass Object
(
[id] => 474
[user_id] => 1
)
[475] => stdClass Object
(
[id] => 475
[user_id] => 1
)
[479] => stdClass Object
(
[id] => 479
[user_id] => 1
)
[480] => stdClass Object
(
[id] => 480
[user_id] => 1
)
)
If key define 474 will result:
Previous array group from key 469 and 468
Next array group from key 475 and 479
If don't have previous and next array, i want no result
I try this method, but not working.
$val = 474;
$currentKey = array_search($val, $array);
$before = (isset($array[$currentKey - 2])) ? $array[$currentKey - 2] :
$after = (isset($array[$currentKey + 2])) ? $array[$currentKey + 2] : $array[0];
var_dump($before, $after);
Please help.
What my method will do is, search for the $key value and return its offset in the array. You were using array_search() on the input array's values, so that's where it fell flat.
Then if the offset value is not false, I attempts to slice the 5 desired subarrays from the input array. If it doesn't return 5, then it fails.
The second code will not trigger a failure if the collection of subarrays is less than 5.
Code: (Demo)
$array=[
467=>(object)['id'=>467,'user_id'=>1],
468=>(object)['id'=>468,'user_id'=>1],
469=>(object)['id'=>469,'user_id'=>1],
474=>(object)['id'=>474,'user_id'=>1],
475=>(object)['id'=>475,'user_id'=>1],
479=>(object)['id'=>479,'user_id'=>1],
480=>(object)['id'=>480,'user_id'=>1]
];
$key=480;
// require 5 subarrays or none:
if(($offset=array_search($key,array_keys($array)))<2 || sizeof($result=array_slice($array,$offset-2,5))!=5){
echo "Fail";
}else{
var_export($result);
}
echo "\n---\n";
// allow any number of subarrays up to 5:
if(($offset=array_search($key,array_keys($array)))===false){
echo "Fail";
}else{
// adjust $offset and $length values to handle array "overflow"
if($offset<2){
$length=$offset+3;
}elseif(($diff=sizeof($array)-$offset)<3){
$length=$diff+2;
}else{
$length=5;
}
$offset=max(0,$offset-2);
var_export(array_slice($array,$offset,$length));
}
Output:
Fail
---
array (
0 =>
stdClass::__set_state(array(
'id' => 475,
'user_id' => 1,
)),
1 =>
stdClass::__set_state(array(
'id' => 479,
'user_id' => 1,
)),
2 =>
stdClass::__set_state(array(
'id' => 480,
'user_id' => 1,
)),
)
Here is a visual representation and some more explanation of what the second method is doing:
The following explanation uses a 6-element array to demonstrate the calculations.
I = 'elements labeled by their indices'
S = 'the slice'
T = 'target index'
L = 'length of slice'
I ST ST ST ST ST ST When $target index is:
0 ╗0 ╗ ╗ 0, then $offset=0 and $length=3
1 ║ ║1 ║ ╗ 1, then $offset=0 and $length=4
2 ╝ ║ ║2 ║ ╗ 2, then $offset=0 and $length=5
3 ╝ ║ ║3 ║ ╗ 3, then $offset=1 and $length=5
4 ╝ ║ ║4 ║ 4, then $offset=2 and $length=4
5 ╝ ╝ ╝5 5, then $offset=3 and $length=3
L: 3 4 5 5 4 3
Since your array is not in the sequence, try this one Demo.
$arr = array( 467 => (object) ['id' => 467, 'user_id' => 1],
468 => (object) ['id' => 468, 'user_id' => 1],
469 => (object) ['id' => 469, 'user_id' => 1],
474 => (object) ['id' => 474, 'user_id' => 1],
475 => (object) ['id' => 475, 'user_id' => 1],
479 => (object) ['id' => 479, 'user_id' => 1],
480 => (object) ['id' => 480, 'user_id' => 1],);
$find = 474;
$before2 = $before1 = $next1 = $next2 = array();
$flag = false;
foreach ($arr as $key => $val) {
if($key == $find) {
$flag = true;
}
if(!$flag) {
if(!empty($before1)){
$before2 = $before1;
}
$before1 = $val;
}
if($key != $find) {
if($flag && empty($next2)){
if(!empty($next1)){
$next2 = $next1;
}
$next1 = $val;
}
if(!empty($next2)){
break;
}
}
}
if($flag) {
echo "matching values =>";
var_dump($before2);
var_dump($before1);
var_dump($next1);
var_dump($next2);
} else {
echo "given index not found!";
}

PHP strange str_split array output

Ok, im having troubles figuring out why my str_split is giving strange array output, this is the code:
$test = array(0 => array(53, 22, 12, "string"),
1 => array(94, 84, 94, "string1"),
2 => array(56, 45, 104, "string2"),
3 => array(33, 21, 20, 23, "string3"),
4 => array(44, 55, 66, 77)
);
$newArray = array();
$keys = array_keys($test);
for($i=0; $i < count($test); $i++){
foreach($test[$keys[$i]] as $key => $value){
}
$output = str_split($key);
echo "<pre>";
print_r($output);
echo "</pre>";
Array output is:
Array
(
[0] => 3
)
Array
(
[0] => 3
)
Array
(
[0] => 3
)
Array
(
[0] => 4
)
Array
(
[0] => 3
)
And im expecting output like this:
Array ([0] => 3
[1] => 3
[2] => 3
[3] => 4
[4] => 3
)
Im wondering why is this happening? Thank you.
To achieve the output given, you would just do:
<?php
$test = array(0 => array(53, 22, 12, "string"),
1 => array(94, 84, 94, "string1"),
2 => array(56, 45, 104, "string2"),
3 => array(33, 21, 20, 23, "string3"),
4 => array(44, 55, 66, 77)
);
foreach ($test as $row) {
$output[] = count($row)-1; // non-associative, so the last key is
} // just the length of the array minus 1
print_r($output);
?>
as the sub-arrays are not associative.
If they are, replace the line inside the loop with:
$keys = array_keys($row); // get the keys of the row
$output[] = $keys[count($keys)-1]; // and access the last of them
with your code the solution is, but it is not an efficient way of doing it.
<?php
$test = array(0 => array(53, 22, 12, "string"),
1 => array(94, 84, 94, "string1"),
2 => array(56, 45, 104, "string2"),
3 => array(33, 21, 20, 23, "string3"),
4 => array(44, 55, 66, 77)
);
$newArray = array();
$keys = array_keys($test);
for($i=0; $i < count($test); $i++){
foreach($test[$i] as $key => $value){
$output[$i] = str_split($key)[0];
}
echo "<pre>";
//print_r($output);
echo "</pre>";
}
var_dump($output);
output
array (size=5)
0 => string '3' (length=1)
1 => string '3' (length=1)
2 => string '3' (length=1)
3 => string '4' (length=1)
4 => string '3' (length=1)
But by changing it to this will work, for arrays when the string position is not constant .
<?php
$test = array(0 => array(53, 22, 12, "string"),
1 => array(94, 84, 94, "string1"),
2 => array(56, 45, 104, "string2"),
3 => array(33, 21, "string3", 20, 23),
4 => array(44, 55, 66, 77)
);
$newArray = array();
$keys = array_keys($test);
for($i=0; $i < count($test); $i++){
foreach($test[$i] as $key => $value){
if(is_string($value)){
unset($test[$i][$key]);
}
$output[$i] = count($test[$i]);
}
echo "<pre>";
//print_r($output);
echo "</pre>";
}
var_dump($output);
output
array (size=5)
0 => int 3
1 => int 3
2 => int 3
3 => int 4
4 => int 4

Append two arrays having same key inside one array differently

I have two array in php likes this :
$a = [ 1 => [ 0 => 10, 1 => 1 ] ] and $b = [ 1 => [ 0 => 15, 1 => 3 ] ]
I have to make a union of these two arrays that resultant array should be like this :
$r = [ 1 => [ 0 => 10, 1 => 1 ], 1 => [ 0 => 15, 1 => 3 ] ]
Please give me idea how can i achieve this ..
Thanks in advance !!
You can't give same array index....index is unique
$r[] = $a;
$r[] = $b;
so your array will be
$r = [ [0]=>[1 => [ 0 => 10, 1 => 1 ]], [1] =>[1 => [ 0 => 15, 1 => 3 ] ]]
You can't have an array with the same key.
If you want to merge values of two arrays, use array_merge:
$a = array(
0 => 10,
1 => 1 ) ;
print_r($a);
echo "<br>";
$b = array(0 => 15,
1 => 3);
print_r($b);
echo "<br>";
$result = array_merge($a, $b);
print_r($result);

Categories