sort associative array by key value - php

I try to sort my array by "delais_livraison" by DESC in php but i dont know how i can do that
In the first level I expected to have in first Etoile => 25 and then Feuillage => 10
Array
(
[A] => Array
(
[0] => Array
(
[Feuillage] => Array
(
[delais_livraison] => 10
)
)
[1] => Array
(
[Étoiles] => Array
(
[delais_livraison] => 25
)
)
)
[B] => Array
(
[0] => Array
(
[Grenouillère] => Array
(
[delais_livraison] => 7
)
)
[1] => Array
(
[Chaussons] => Array
(
[delais_livraison] => 0
)
)
)
)
Edit :
this how my array has been build
pastebin

Just try with:
$data = array(
'A' => array(
array('Feuillage' => array('delais_livraison' => 10)),
array('Étoiles' => array('delais_livraison' => 25)),
),
'B' => array(
array('Grenouillère' => array('delais_livraison' => 7)),
array('Chaussons' => array('delais_livraison' => 0)),
),
);
foreach ($data as &$group) {
usort($group, function($itemA, $itemB){
$a = current($itemA)['delais_livraison'];
$b = current($itemB)['delais_livraison'];
if ($a == $b) return 0;
return ($a > $b) ? -1 : 1;
});
}
Output:
array (size=2)
'A' =>
array (size=2)
0 =>
array (size=1)
'Étoiles' =>
array (size=1)
'delais_livraison' => int 25
1 =>
array (size=1)
'Feuillage' =>
array (size=1)
'delais_livraison' => int 10
'B' => &
array (size=2)
0 =>
array (size=1)
'Grenouillère' =>
array (size=1)
'delais_livraison' => int 7
1 =>
array (size=1)
'Chaussons' =>
array (size=1)
'delais_livraison' => int 0
Solution uses anonymous function that has been introduced in PHP 5.3.0. For older versions just create a function and specify it in usort function:
function my_sort_function($itemA, $itemB){
// ...
}
usort($group, 'my_sort_function');

Since your array has two levels, how do you want to manage a global sort ?
Do you want to do a sort for each sub array ( A, B, ...) ?
In this case the approach will be to use function uksort for each sub array (A and B) and define your own compare function to compare delais_livraison values.

You would appear to be looking for ksort, or, if you have to supply your own comparison function, uksort.

Related

Array merge or push key and values of one array into another array

I have 2 arrays and want to add key & value of one array into each member of another array.
The first array is :
Array
(
[0] => Array
(
[supply_id] => 2
)
[1] => Array
(
[supply_id] => 4
)
[2] => Array
(
[supply_id] => 5
)
)
The second array is :
Array
(
[status] => 1
[t1_id] => 59
)
The result I need is :
Array
(
[0] => Array
(
[supply_id] => 2,
[status] => 1,
[t1_id] => 59,
)
[1] => Array
(
[supply_id] => 4,
[status] => 1,
[t1_id] => 59,
)
[2] => Array
(
[supply_id] => 5,
[status] => 1,
[t1_id] => 59,
)
)
It looks easy I think , but I could not solve it, any body can help me please ?
you can try this:
$res = array();
foreach($secondArray as $k => $v){
$res[$k] = array_merge($secondArray[$k], $firstArray[$k]);
}
Loop through first array then merge values in new array:
$array_1= array
(
0 => array
(
"supply_id" => 2
),
1 => array
(
"supply_id" => 4
),
2 => array
(
"supply_id" => 5
),
);
$array_2=array
(
"status" => 1,
"t1_id" => 59
);
$new_array = array();
foreach ($array_1 as $key => $value) {
$new_array[] = array_merge($value,$array_2);
}
var_dump($new_array);
o/p:
array (size=3)
0 =>
array (size=3)
'supply_id' => int 2
'status' => int 1
't1_id' => int 59
1 =>
array (size=3)
'supply_id' => int 4
'status' => int 1
't1_id' => int 59
2 =>
array (size=3)
'supply_id' => int 5
'status' => int 1
't1_id' => int 59
Here we are using simple foreach loop for achieving desired output.
Try this code snippet here
foreach($firstArray as $key => &$value)
{
$value= array_merge($value,$secondArray);
}
print_r($array);

Traverse an array and compare the current key value pair with next one php

Am trying to compare the key value pair of an array to compare the next key value pair to find the lower one value.if found the lower the higher one was to be unset and move forward.But am not getting the accuracy,what am doing wrong here,please suggest.Here is the code.
This is the array which is to be compared and evaluated.
Array
(
[0] => Array
(
[com_details] => Array
(
[spid] => 6
)
[distance] => 13.1 mi
)
[1] => Array
(
[com_details] => Array
(
[spid] => 6
)
[distance] => 66.2 mi
)
[2] => Array
(
[com_details] => Array
(
[spid] => 6
)
[distance] => 1.5 mi
)
[3] => Array
(
[com_details] => Array
(
[spid] => 7
)
[distance] => 188 mi
)
[4] => Array
(
[com_details] => Array
(
[spid] => 7
)
[distance] => 96.7 mi
)
[5] => Array
(
[com_details] => Array
(
[spid] => 7
)
[distance] => 3.1 mi
)
[6] => Array
(
[com_details] => Array
(
[spid] => 14
)
[distance] => 1.8 mi
)
[7] => Array
(
[com_details] => Array
(
[spid] => 14
)
[distance] => 228 mi
)
[8] => Array
(
[com_details] => Array
(
[spid] => 14
)
[distance] => 82.2 mi
)
)
In the above array i need to compare those com_details whose spid is same and the distance is different,If the next or prev distance is small then the other one will be unset and move forward for next iteration.But am failing to this end point.
$l=0;
do{
$length = count($dispatch_locations1);
if($length >= $l+1){
if($dispatch_locations1[$l]['com_details']['spid'] == #$dispatch_locations1[$l+1]['com_details']['spid']){
if($dispatch_locations1[$l]['distance'] > $dispatch_locations1[$l+1]['distance']){
unset($dispatch_locations1[$l]);
$l--;
$dispatch_locations1 = array_values($dispatch_locations1);
} else if($dispatch_locations1[$l]['distance'] < $dispatch_locations1[$l+1]['distance']){
unset($dispatch_locations1[$l+1]);
$l--;
$dispatch_locations1 = array_values($dispatch_locations1);
} else if($dispatch_locations1[$l]['distance'] == $dispatch_locations1[$l+1]['distance']){
unset($dispatch_locations1[$l+1]);
$l--;
$dispatch_locations1 = array_values($dispatch_locations1);
}
}
}
$l++;
} while ($l <= count($dispatch_locations1)+1);
}
after the full iterations am getting this array which is somewhat wrong.
Array
(
[0] => Array
(
[com_details] => Array
(
[spid] => 6
)
[distance] => 1.5 mi
)
[1] => Array
(
[com_details] => Array
(
[spid] => 7
)
[distance] => 188 mi
)
[2] => Array
(
[com_details] => Array
(
[spid] => 14
)
[distance] => 1.8 mi
)
)
In this result the second array distance returning is 188 which is wrong.
Please suggest what am doing wrong here.
You could simplify the Entire complex operation by abridging your code. The Code Snippet below demonstrates how but, before you begin, you may want to try & test it our yourself here.
THE SAMPLE ARRAY USED HERE FOR TESTING
<?php
$arrMain = array(
array(
'com_details' => array('spid'=> 6),
'distance' => "13.1mi",
),
array(
'com_details' => array('spid'=> 6),
'distance' => "66.2 mi",
),
array(
'com_details' => array('spid'=> 6),
'distance' => "1.5mi",
),
array(
'com_details' => array('spid'=> 7),
'distance' => "188.0 mi",
),
array(
'com_details' => array('spid'=> 7),
'distance' => "96.7 mi",
),
array(
'com_details' => array('spid'=> 7),
'distance' => "3.1 mi",
),
array(
'com_details' => array('spid'=> 14),
'distance' => "1.8 mi",
),
array(
'com_details' => array('spid'=> 14),
'distance' => "228.0 mi",
),
array(
'com_details' => array('spid'=> 14),
'distance' => "82.2 mi",
),
);
THE ALGORITHM
<?php
$arrSections = array();
// SORTING FUNCTION - USED TO SORT ARRAY VALUES BY "distance"
// IN DESCENDING ORDER...
function sortByField($prev, $next, $field="distance") {
$prevVal = floatval(preg_replace("#[a-zA-Z\s\t]*#", "",$prev[$field]));
$nextVal = floatval(preg_replace("#[a-zA-Z\s\t]*#", "",$next[$field]));
return $prevVal - $nextVal;
}
// BUNDLE ARRAYS WITH SIMILAR spid INTO ONE GROUP
// THUS CREATING A MULTI-DIMENSIONAL ARRAY WHOSE MAIN KEYS CORRESPOND TO
// THE spid OF MEMBER ARRAYS IN THE GROUP.
foreach($arrMain as $iKey=>$subMain){
$spID = $subMain['com_details']['spid'];
$strID = $spID;
if(!array_key_exists($strID, $arrSections)) {
$arrSections[$strID] = array();
}
$arrSections[$strID][] = $subMain;
}
// SORT THE ARRAY SIMPLY BY THE FIELD "distance" IN DESCENDING ORDER
array_walk($arrSections, function (&$data) {
usort($data, "sortByField");
});
// ARRAY THAT HOLDS THE DESIRED RESULT
$arrFinal = array();
// WE KNOW THAT ONLY THE FIRST ITEM IN THE ARRAY IS OF IMPORTANCE TO US
// SO WE REMOVE ALL OTHER ITEMS EXCEPT THE 1ST...
foreach($arrSections as $intKey=>&$section){
array_splice($section, 1);
$arrFinal[] = $section[0];
}
var_dump($arrFinal);
THE RESULT OF THE VAR_DUMP()
// var_dump($arrSections); PRODUCES:::
array (size=3)
0 =>
array (size=2)
'com_details' =>
array (size=1)
'spid' => int 6
'distance' => string '1.5mi' (length=5)
1 =>
array (size=2)
'com_details' =>
array (size=1)
'spid' => int 7
'distance' => string '3.1 mi' (length=6)
2 =>
array (size=2)
'com_details' =>
array (size=1)
'spid' => int 14
'distance' => string '1.8 mi' (length=6)
If i get your problem correctly here is the code to solve that..
this code sorts array first by spid and than by distance:
<?php
usort($dispatch_locations1, function($a, $b) {
if($a['com_details']['spid'] > $b['com_details']['spid']) {
return 1;
} elseif($a['com_details']['spid'] < $b['com_details']['spid']) {
return -1;
}
return (floatval($a['distance']) < floatval($b['distance'])) ? -1 : 1;
});
?>

How to append value to all subarrays in PHP without a loop? [duplicate]

This question already has answers here:
PHP Add element to every sub array of multi dimension array
(3 answers)
Closed 2 years ago.
I have the following array:
Array (
[0] => Array (
'id' => ...
'name' ...
),
[1] => Array (
'id' => ...
'name' ...
),
[2] => Array (
'id' => ...
'name' ...
),
[3] => Array (
'id' => ...
'name' ...
),
)
What I want to do is to append the same pid key-value pair to every subarray. Is there an easy way to do this without having to do a foreach?
without having to explicitly use a foreach or some other kind of loop, you can use PHP's array_map function. although this will perform an iterated loop under the hood, it will return an array with each element processed by your function.
<?php
$arr = Array (
0 => Array (
'id' => 1,
'name' => 'one'
),
1 => Array (
'id' => 2,
'name' => 'two'
),
2 => Array (
'id' => 3,
'name' => 'three'
),
3 => Array (
'id' => 4,
'name' => 'four'
)
);
function append_pid_kvpair($n){
$n ['pid']= 'value';
return $n;
}
$arr = array_map("append_pid_kvpair",$arr);
echo "<pre>".print_r($arr,true)."</pre>";
will result in this output
Array
(
[0] => Array
(
[id] => 1
[name] => one
[pid] => value
)
[1] => Array
(
[id] => 2
[name] => two
[pid] => value
)
[2] => Array
(
[id] => 3
[name] => three
[pid] => value
)
[3] => Array
(
[id] => 4
[name] => four
[pid] => value
)
)

Add column of values from one array to another

Here is array #1
Array
(
[0] => Array
(
[first] => LightSpeed
[last] => Administrator
)
[1] => Array
(
[first] => Tyler
[last] => Nichol
)
Here is array #2
Array
(
[I-10] => Array
(
[user] => 2
[total] => 46.64
)
[I-11] => Array
(
[user] => 2
[total] => -46.64
)
I just want to add [total] => $value to the first array so it looks like.
Array
(
[0] => Array
(
[first] => LightSpeed
[last] => Administrator
[total] => 46.64
)
[1] => Array
(
[first] => Tyler
[last] => Nichol
[total] => -46.64
)
Pretty sure it is array_push but not sure how to loop it. Any suggestions? Thanks!
It's a bit low tech, but I'd just loop through your array and insert the total item. Assuming you're just matching to the second array on the position of the items in the arrays:
$vals = array_values($arr2);
foreach($arr1 as $i=>$item) {
$arr1[$i]['total'] = $vals[$i]['total'];
}
Your array is not well formatted so I have done that in my answer. You might want to update your question
<?php
$arr1 = Array
(
Array
(
'first' => 'LightSpeed',
'last' => 'Administrator'
),
Array
(
'first' => 'Tyler',
'last' => 'Nichol'
)
);
$arr2 = Array
(
'I-10' => Array
(
'user' => 2,
'total' => 46.64
),
'I-11' => Array
(
'user' => 2,
'total' => -46.64
)
);
$n = count($arr1);
$i = 0;
foreach($arr2 as $arr)
{
$arr1[$i]['total'] = $arr['total'];
$i++;
}
var_dump($arr1);
?>
Result of var_dump
array
0 =>
array
'first' => string 'LightSpeed' (length=10)
'last' => string 'Administrator' (length=13)
'total' => float 46.64
1 =>
array
'first' => string 'Tyler' (length=5)
'last' => string 'Nichol' (length=6)
'total' => float -46.64
You don't have to loop all the time .. array_merge can do the trick
function superMerge($a, $b) {
$a['total'] = $b['total'];
return $a;
}
$array1 = array(0 => Array("first" => "LightSpeed","last" => "Administrator"),1 => Array("first" => "Tyler","last" => "Nichol"));
$array2 = array("I-10" => Array("user" => 2,"total" => 46.64),"I-11" => Array("user" => 2,"total" => - 46.64));
var_dump(array_map("superMerge", $array1, $array2));
Output
array
0 =>
array
'first' => string 'LightSpeed' (length=10)
'last' => string 'Administrator' (length=13)
'total' => float 46.64
1 =>
array
'first' => string 'Tyler' (length=5)
'last' => string 'Nichol' (length=6)
'total' => float -46.64

Sorting a table in PHP

I have some difficulty sorting my array. It looks like this :
[0] => Array
(
[firstname] => Jnic
[lastname] => Fortin
[points] => Array
(
[id] => 20453
[f] => 31
[r] => 7
[total] => 82
)
)
[1] => Array
(
[firstname] => Kris
[lastname] => Anders
[points] => Array
(
[id] => 20309
[f] => 0
[r] => 1
[total] => 56
)
)
[2] => Array
(
[firstname] => Em
[lastname] => Zajo
[points] => Array
(
[id] => 20339
[f] => 8
[r] => 3
[total] => 254
)
)
I would like to sort it by "total" DESC. How could I do it? If everything sort ok the array would be order [2][0][1] (254,82,56)
You probably can use the usort function for that : it sorts an array, using a callback function to compare the elements of that array :
bool usort ( array &$array , callback $cmp_function )
This function will sort an array by
its values using a user-supplied
comparison function. If the array you
wish to sort needs to be sorted by
some non-trivial criteria, you should
use this function
If your function is defined to compare per $element['points']['total'], it should do the trick.
Edit : And here is the example, using uasort, which is the same as usort, but will keep the array keys, like pointed out by ryanday :
First, let's declare the array :
$a = array(
array(
'firstname' => 'Jnic',
'lastname' => 'Fortin',
'points' => array(
'id' => 20453,
'f' => 31,
'r' => 7,
'total' => 82,
),
),
array(
'firstname' => 'Kris',
'lastname' => 'Anders',
'points' => array(
'id' => 20309,
'f' => 0,
'r' => 1,
'total' => 56,
),
),
array(
'firstname' => 'Em',
'lastname' => 'Zajo',
'points' => array(
'id' => 20339,
'f' => 8,
'r' => 3,
'total' => 254,
),
),
);
And then, the comparison function :
function my_compare($a, $b) {
if ($a['points']['total'] > $b['points']['total']) {
return -1;
} else if ($a['points']['total'] < $b['points']['total']) {
return 1;
}
return 0;
}
And, finally, we use it :
uasort($a, 'my_compare');
var_dump($a);
And get the array, sorted by total desc :
array
2 =>
array
'firstname' => string 'Em' (length=2)
'lastname' => string 'Zajo' (length=4)
'points' =>
array
'id' => int 20339
'f' => int 8
'r' => int 3
'total' => int 254
0 =>
array
'firstname' => string 'Jnic' (length=4)
'lastname' => string 'Fortin' (length=6)
'points' =>
array
'id' => int 20453
'f' => int 31
'r' => int 7
'total' => int 82
1 =>
array
'firstname' => string 'Kris' (length=4)
'lastname' => string 'Anders' (length=6)
'points' =>
array
'id' => int 20309
'f' => int 0
'r' => int 1
'total' => int 56
ryanday > Thanks for your answer !
You will want to use usort as answered by #Pascal MARTIN, but here is the full code to achieve what you want:
function total_sort($a, $b){
$a_total = $a['points']['total'];
$b_total = $b['points']['total'];
if($a_total == $b_total) return 0;
return ($a_total > $b_total) ? -1 : 1;
}
usort($array, "total_sort");
EDIT: After I posted I saw #Pascal updated his answer to include a sample. Since I wrote my sort function a little different, I am leaving it here as another reference.
usort is a robust solution that can be very flexible for complex cases. Since your data set is relatively simple i would suggest the following:
// assuming your array has been defined in $a
$sort = array();
foreach ($a as $key => $suba)
{
// this collects the values you want to sort by and associates them with the correct index
$sort[$key] = $suba['points']['total'];
}
// this sorts the collected values
sort($sort);
// this re-sorts $a according to the sorted $sort array
array_multisort($a, $sort);
not sure about performance but this is at least AS GOOD as usort if not better
I noticed you said the proper array should be ordered [2][0][1], if that index association is important to you follow Pascal's advice with the uasort() function.

Categories