sorting some weird array in php by a value - php

How can i sort something like this
$a = array(
0 => array(
'field' => array(
'id'=>'valueid'
)
)
);
by valueid? I have managed to sort it by field but i can't realize how to do this weird sorting

usort($a, function($e1, $e2) {
return $e1['field']['id'] > $e2['field']['id'];
});

Use uasort()
uasort($a, function($x, $y) {
return $x['field']['id'] > $y['field']['id'];
});

Related

PHP sorting a 2-dimensional array by multiple subkeys

I have an array as follows:
//0-based index, 2 dimensions
$data = array(
array(
'name'=>'EJA210E',
'id'=>439,
'region_id'=>17,
.. other attributes ..
),
array(
'name'=>'EJA210E',
'id'=>440,
'region_id'=>3,
),
array(
'name'=>'EJA210E',
'id'=>439,
'region_id'=>15,
),
.. etc..
);
What would be sort, first by name, then by id, then by region_id? Sorting by any one of these is no problem; I would simply loop through and get the name attribute, then re-order, however doing this three times I do not understand how to do.
You can try array_multisort by passing different ordering columns as shown below :
$data = array(
array(
'name'=>'EJA210E',
'id'=>439,
'region_id'=>17,
),
array(
'name'=>'EJA210E',
'id'=>440,
'region_id'=>3,
),
array(
'name'=>'AJA210E',
'id'=>438,
'region_id'=>15,
)
);
// Obtain a list of columns
foreach ($data as $key => $row) {
$name[$key] = $row['name'];
$id[$key] = $row['id'];
$region[$key] = $row['region_id'];
}
// Sort the data with volume descending, edition ascending
// Add $data as the last parameter, to sort by the common key
array_multisort($name, SORT_DESC, $id, SORT_DESC,$region, SORT_DESC, $data);
You could use usort() with a custom sorting function. Here's an example:
function cmp($a, $b)
{
if ($a['name'] == $b['name']) {
if ($a['id'] == $b['id']) {
if ($a['region_id'] == $b['region_id']) {
return 0;
}
return $a['region_id'] < $b['region_id'] ? -1 : 1;
}
return $a['id'] < $b['id'] ? -1 : 1;
}
return ($a['name'] < $b['name']) ? -1 : 1;
}
usort($data, 'cmp');

Sorting in Multi Dimension array in php

When I am adding same unit of number in "num". eg(0-9). It is sorting my array. But if any of the "num" value contains a different unit of digits, the sorting fails. eg(4,7,2,1) this will work. (7,12,76,2) this will fail.
$stack = array(array("Price" => $op,"num" => $noi),
array("Price" => $op1,"num" => $noi1),
array("Price" => $op2,"num" => $noi2),
array("Price" => $op3,"num" => $noi3));
function cmp($a, $b)
{
return strcmp($a["num"], $b["num"]);
}
usort($stack, "cmp");
Try this for comparison of numbers
function cmp($a, $b) {
if ($a['num'] == $b['num']) {
return 0;
}
return ($a['num'] < $b['num']) ? -1 : 1;
}
It is taken straight out of the PHP manual on usort, and modified for your array.

find and sort array by lowest value in multidimensional array

I have an array that contains a number of arrays. Like this:
array{
array{
id => 1
name => place_1
lat => 56.1705
lon => 10.2010
distance => 1.545
}
array{
id => 14
name => place_14
lat => 56.1715
lon => 10.2049
distance => 1.765
}
//etc etc
}
I need to sort the arrays within the array by distance, from low to high - or at least get the position of the lowest distance in the array (like $array[1][4] == 1.765).
I have done something similar before. Then I did it with a function like this:
function sort_by_dist($a, $b){
return $a['distance'] - $b['distance'];
}
usort($array, 'sort_by_dist');
However, this will in this case only return bool(true)
I have no idea why it acts this way.
I know this question has probably been asked (and answered) before, but as a non-native speaker of English I am a bit at a loss as to what I should search for.
Thank you for your help!
My answer just reformats your function a little to make it more explicit what is going on:
$a = array(
array(
'id' => 14,
'name' => 'place_14',
'lat' => 56.1715,
'lon' => 10.2049,
'distance' => 1.765,
),
array(
'id' => 1,
'name' => 'place_1',
'lat' => 56.1705,
'lon' => 10.2010,
'distance' => 1.545,
),
);
usort($a, function($a, $b) {
$d1 = $a['distance'];
$d2 = $b['distance'];
if ($d1 == $d2) {
return 0;
}
return ($d1 < $d2) ? -1 : 1;
});
// the array $a is sorted.
print_r($a);
The input array to usort is sorted, usort will return false if the sorting failed and true otherwise.
You can use array_multisort by iterating thought the array like so:
function sort_by(&$array, $subkey ) {
foreach ($array as $subarray) {
$keys[] = $subarray[$subkey];
}
array_multisort($keys, SORT_ASC, $array);
}
sort_by($coords, 'distance');// $coords is now sorted by distance
$coords is your multidimensional array.

How to sort all levels of multidimensional array by key?

I found this code for sorting:
usort($array, function($a, $b) {
return $a['order_inside_level'] - $b['order_inside_level'];
});
It's good for one level. I have something like that:
array(
array(
'level'=>'aaa',
'order'='1',
'subs'=>array(
array(
'level'=>'bbb',
'order'='1',
'subs'=>array(
array(
'level'=>'ccc',
'order'='1',
'subs'=>array(
array(
'level'=>'ddd',
'order'='1',
'subs'=>array(
...
)
)
)
)
,
array(
'level'=>'ccc',
'order'='2',
'subs'=>array(
)
)
),
array(
'level'=>'bbb',
'order'='2'
),
array(
'level'=>'bbb',
'order'='3'
)
)
)
),
array(
'level'=>'aaa',
'order'='2',
'subs'=>array(
)
)
)
Array may have any depth and any number of elements in each level. I need to sort each level of depth (aaa,bbb,ccc, etc) using the code above by key 'order'.
You will need to do this recursively.
recursive_sort($arr, $func) {
foreach ($arr as $key => $val) {
if (is_array($val)) {
recursive_sort($val, $func);
}
}
usort($arr, $func);
}
This code will iterate over the given array, and for each value that is an array, call itself with the value. The result is that usort will be called for every array within the structure.
You would call the function the same as you would usort:
recursive_sort($array, function($a, $b) {
return $a['order_inside_level'] - $b['order_inside_level'];
});
function recursive_sort(&$arr) {
fs($arr);
foreach($arr as $k=> &$v){
if (isset($v['subs'])) {
recursive_sort($v['subs']);
}
}
}
function sortByOrder($a, $b) {
return $a['order_inside_level'] - $b['order_inside_level'];
}
function fs(&$array){
usort($array, 'sortByOrder');
}
After multiple tries I have this. It works. Name of key (subs) is hardcoded what is not so good, but... I am glad it works.

PHP-Sort array based on another array?

OK, I already got this question in stackoverflow but sadly it's in javascript - Javascript - sort array based on another array
and I want it in PHP
$data = array(
"item1"=>"1",
"item2"=>"3",
"item3"=>"5",
"item4"=>"2",
"item5"=>"4"
);
to match the arrangement of this array:
sortingArr = array("5","4","3","2","1");
and the output I'm looking for:
$data = array(
"item3"=>"5",
"item5"=>"4",
"item2"=>"3",
"item4"=>"2",
"item1"=>"1"
);
Any idea how this can be done?
Thanks.
For a detailed answer, why array_multisort does not match your needs, view this answer, please:
PHP array_multisort not sorting my multidimensional array as expected
In short: You want to sort an array based on a predefined order. The Answer is also given over there, but i copied one solution to this answer, too:
Use usort and array_flip, so you be able to turn your indexing array (ValueByPosition) into a PositionByValue Array.
$data = array(
"item1"=>"1",
"item2"=>"3",
"item3"=>"5",
"item4"=>"2",
"item5"=>"4"
);
usort($data, "sortByPredefinedOrder");
function sortByPredefinedOrder($leftItem, $rightItem){
$order = array("5","4","3","2","1");
$flipped = array_flip($order);
$leftPos = $flipped[$leftItem];
$rightPos = $flipped[$rightItem];
return $leftPos >= $rightPos;
}
print_r($data);
// usort: Array ( [0] => 5 [1] => 4 [2] => 3 [3] => 2 [4] => 1 )
// uasort: Array ( [item3] => 5 [item5] => 4 [item2] => 3 [item4] => 2 [item1] => 1 )
However this would require you to predict all possible items inside the predefined order array, or thread other items in an appropriate way.
If you want to maintain the assoc keys, use uasort instead of usort.
Pretty simple ?
$data = array(
"item1"=>"1",
"item2"=>"3",
"item3"=>"5",
"item4"=>"2",
"item5"=>"4"
);
$sortingArr = array("5","4","3","2","1");
$result = array(); // result array
foreach($sortingArr as $val){ // loop
$result[array_search($val, $data)] = $val; // adding values
}
print_r($result); // print results
Output:
Array
(
[item3] => 5
[item5] => 4
[item2] => 3
[item4] => 2
[item1] => 1
)
using usort() the right way i think
Sort an array by values using a user-defined comparison function
you can do as follow:
$data = array(
"item1"=>"1",
"item2"=>"3",
"item3"=>"5",
"item4"=>"2",
"item5"=>"4"
);
$sortingArr = array("5","4","3","2","1");
$keys = array_flip($sortingArr);
usort($data, function ($a, $b) use ($keys) {
return $keys[$a] > $keys[$b] ? 1 : -1;
});
print_r($data);
// Output
// Array ( [0] => 5 [1] => 4 [2] => 3 [3] => 2 [4] => 1 )
live example: https://3v4l.org/75cnu
Look at my following snippet to sort your array based on another array:
$res_arr = array();
for ($i = 0; $i < count($sortingArr); $i++) {
for ($j = 0; $j < count($data); $j++) {
if($data[$j] == $sortingArr[$i]) {
$res_arr[] = $data[$j];
break;
}
}
}
// $res_array is your sorted array now
Look at code snippet to make a multidimensional array sort in order of input
$input_format_list = [4, 1];
$data = array(
"0" => array(
"School" => array(
"id" => 1,
"name" => "ST.ANN'S HIGH SCHOOL",
)
),
"1" => array(
"School" => array(
"id" => 4,
"name" => "JYOTI VIDHYA VIHAR",
)
)
);
$result = array(); // result array
foreach($input_format_list as $key => $value){ // loop
foreach ($data as $k => $val) {
if ($data[$k]['School']['id'] === $value) {
$result[$key] = $data[$k];
}
}
}
return $result;
Take a look at array_multisort. I'm not completely sure how to use it, as I have never found a practical use for it (I prefer to use usort to clearly define my terms), but it might work for you.
<?php
$data = array(
"item1"=>"1",
"item2"=>"3",
"item3"=>"5",
"item4"=>"2",
"item5"=>"4"
);
$result=array_flip($data);
krsort($result);
$result=array_flip($result);
print_r($result);
//use rsort for the index array
$sortingArr = array("5","4","3","2","1");
print_r($sortingArr);
I'm pretty proud of my solution:
uasort($data, function($a, $b) use ($sortingArr) {
return array_search($a, $sortingArr) <=> array_search($b, $sortingArr);
});
Working example: https://3v4l.org/bbIk2
It uses uasort to maintain the key-value associations as the OP requested. (unlike #hassan's otherwise elegant solution)
It doesn't require that every element in the $data array be present in the sorting array. (like #HamZa's solution)
It's brief.
It uses the spaceship operator <=> for comparison instead of more verbose logic.
Code:
Expanding on the Answer of Andrew, if you want the undefined entries in the sorting array to appear at the end of the output array:
uasort($currentTags, function ($a, $b) use ($sortingArr) {
if (in_array($a, $sortingArr) && !in_array($b, $sortingArr)) return -1;
if (!in_array($a, $sortingArr) && in_array($b, $sortingArr)) return 1;
if (!in_array($b, $sortingArr)) return -1;
return array_search($a, $sortingArr) <=> array_search($b, $sortingArr);
});

Categories