This question already has answers here:
Sort multidimensional array by multiple columns
(8 answers)
Closed 10 months ago.
I went through all the similiar questions but couldn't find an answer....so here goes.
My current array, simplified:
[order] => Array
(
[0] => Array
(
[strSupplier] => XYZ
(varying other fields)
)
[1] => Array
(
[strSupplier] => XYZ
(varying other fields)
)
[2] => Array
(
[strSupplier] => YYZ
(varying other fields)
)
)
Code:
function custom_sort2($a,$b) {
return $a['strSupplier']>$b['strSupplier'];
}
// Sort the multidimensional array
usort($tempOrderArray, "custom_sort2");
Currently, I am sorting on only the supplier, however, I need to ensure that the key is the second sort criteria, and I am not sure that it is.
Is there a way I can guarantee that it is sorted by strSupplier first, then key? If this is built into either the uasort or usort function, I apologize - I did not see it.
Your array would like this this:
[order] => Array
(
[0] => Array
(
[key] => 0,
[strSupplier] => 'XYZ',
//(varying other fields)
)
[1] => Array
(
[key] = 1,
[strSupplier] => 'XYZ',
//(varying other fields)
)
[2] => Array
(
[key] = 2,
[strSupplier] => 'YYZ',
//(varying other fields)
)
)
Then, when you sort:
function custom_sort2($a, $b) {
$cmp = $cmpstr = strcmp($a['strSupplier'], $b['strSupplier']); //Compare the string
$cmpkey = ($a['key'] == $b['key'] ? 0 : ($a['key'] > $b['key'] ? 1 : -1)); //Compare the key
if ($cmpkey == 1)
$cmp = ($cmpstr >= 0) ? 1 : 0;
return $cmp; //If we are moving the element forward, then we need to check the key.
}
// Sort the multidimensional array
uasort($array, "custom_sort2");
You could try using ksort first, and then sort by supplier.
Related
I'm using an array with PHP's uasort function. If $a[0]['date'] == $b[0]['date'], then I do not want to sort.
Anyway, my code will sort anyway. How could I prevent it from doing so?
Here is my array:
And here is the array:
Array (
[2764] => Array (
[status] => 0
[0] => Array (
[date] => 2000-01-01
)
[1] => Array (
[date] => 2016-01-16
)
)
[5974] => Array (
[status] => 0
[0] => Array (
[date] => 2000-01-01
)
[1] => Array (
[date] => 2010-12-13
)
)
)
And here is how I'm trying to sort:
uasort($arr, function($a, $b)
{
if ($a['status'] == $b['status'])
{
if ($a[0]['date'] == $b[0]['date'])
{
return 0; # I do not want to sort here, but this will sort anyway - why is that so?
}
else
{
return strcmp($a[0]['date'], $b[0]['date']);
}
}
else
{
return $b['status'] - $a['status'];
}
});
How could I sort by indexes if dates are same? I mean sorting by indexes 2764 and 5974.
As in documentation:
If two members compare as equal, their relative order in the sorted array is undefined.
So you have to introduce extra value, such as original_order and sort by it equal entries.
I have this array of options, and some value of an internal array is the "ID"
[options] => Array (
[0] => Array (
[id] => 1088
[label] => John
)
[1] => Array (
[id] => 1089
[label] => Peter
)
[2] => Array (
[id] => 1050
[label] => Mary
)
....
On the other hand, I have this array:
$array_sort = array(1089, 1050, 1088, ...);
I would like the options array of the first array is sorted (looking the "id") based on the $array_sort.
I know how to do it in a very dirty way (with a lot of loops and temporary arrays), but I guess there's some smart solution of array_* functions to do this.
Thank you !
You could use array_filter to limit the options to only those in the sorted array, then usort to sort them based on their position in the $array_sort array using array_search:
$sorted = array_filter($options, function($arr) use($array_sort) {
return in_array($arr['id'], $array_sort);
});
usort($sorted, function($a, $b) use($array_sort) {
return array_search($a['id'], $array_sort) - array_search($b['id'], $array_sort);
});
// $sorted should now be the sorted array
I have following two multidimensional arrays:
First array:
$array_1_data = Array (
[0] => Array ( [id] => 1 [name] => IT [slug] => it )
[1] => Array ( [id] => 2 [name] => Accounting [slug] => accounting )
)
Second array:
$array_2_data = Array (
[0] => Array ( [cid] => 3 [jid] => 24061 )
[1] => Array ( [cid] => 1 [jid] => 24062 )
)
Expected result:
$some_array = Array (
[0] => Array ( [id] => 1 [name] => IT [slug] => it )
)
I won't mind having [cid] in the result.
I want to intersect these two arrays by [id] of the first array and [cid] of the second array, like inner join in MySQL. I have basic foreach and if else logic for this purpose but speed is a priority now so I'm looking for non-looped solution. For better understanding here is the basic looped solution:
foreach ($array_1_data as $array_1_row ) {
foreach ($array_2_data as $array_2_row ) {
if ($array_2_row['cid'] == $array_1_row['id']) {
//intersection iteration
}
}
}
I tried array_uintersection as follows:
array_uintersect($array_1_data, $array_2_data, function($a1, $a2){
$diff1 = strcasecmp($a1['id'], $a2['cid']);
if ($diff1 != 0) return $diff1;
return 0;
});
But it gives me undefined index 'id'. I checked this question: Comparing two arrays with different key names. First answer for this question gives a looped solution which I want to avoid. Second answer suggests changing SQL structure but I have no control over that. So,
Is there really a non-looped fast solution to this kind of situation?
The solution using array_uintersect_uassoc function:
$result = array_uintersect_uassoc($array_1_data, $array_2_data, function($a, $b){
return strcasecmp($a['id'], $b['cid']);
}, function($a, $b){
return (int) [$a, $b] == ['id', 'cid'];
});
print_r($result);
The output:
Array
(
[0] => Array
(
[id] => 1
[name] => IT
[slug] => it
)
)
According yo your condition: to intersect these two arrays by [id] of the first array and [cid] of the second array, we should consider a key comparison function for those keys only ['id', 'cid'].
Having the needed keys on each comparison step it only remain to compare their values(with value compare function)
http://php.net/manual/en/function.array-uintersect-uassoc.php
DEMO link
I have a multidimensional array, and I am trying to sort it so that the array with the most entries comes first, etc... Then if two arrays have the same number of entries, they should be arranged alphabetically. Also, if the entries could be sorted by the key, 'name', I think that would be great. As you can see below, I am using ldap_sort to sort by 'name'. But I'm sure calling too many sort functions is bad practice.
if ($conn == True ) {
Try {
// Authenticate
$bind = ldap_bind($conn, $user, $pass);
// Search AD
$search = ldap_search($conn, $dn, $filter, $attr);
// Sort
ldap_sort($conn, $search, 'name');
// Retrieve Data
$records = ldap_get_entries($conn, $search);
Foreach ($records as $record) {
if(is_array($record) && array_key_exists('l', $record)) {
$locations[$record['l'][0]][] = $record;
}
continue;
}
} finally {
// Close Connection
ldap_close($conn);
}
} else {
trigger_error('Unable_To_Connect_To_Server');
}
// Sort Location By Number Of Entries
array_multisort(array_map('count', $locations), SORT_DESC, $locations);
I guess to put it layman's terms.. Sorting entries alphabetically by their 'name' value, should be inherent. Then the arrays should be sorted by the number of entries, and if any arrays have the same number of entries they should be sorted alphabetically.
P.S. - I'm asking for help because it's hard for me to understand multidimensional arrays (especially those returned by ldap_search) and sorting them is even more mind-boggling to me.
EDIT Like I said, arrays confuse me but hopefully the below accurately depicts my intentions:
Array (
[Location1] => Array (
[0] => Array (
[l] => Array (
[count] => 1
[0] => Location1
)
[0] => l
[telephonenumber] => Array (
[count] => 1
[0] => XXX.XXX.XXXX
)
[1] => telephonenumber
[department] => Array (
[count] => 1
[0] => Department1
)
[2] => department
[name] => Array (
[count] => 1 [0] => User1
)
[3] => name
[ipphone] => Array (
[count] => 1
[0] => IPPhone1
)
[4] => ipphone
[mail] => Array (
[count] => 1
[0] => user#domain.com
)
[5] => mail
[count] => 6
[dn] => DistinguishedName1
)
)
)
I cut the above short (there are hundreds of records returned) and I'm not sure I ended it correctly. But I am essentially parsing the information to output something like below.
c_Location1
a_user1
b_user1
c_user1
a_Location2
a_user2
b_user2
b_location3
a_user3
b_user3
Write a function that compares the lengths of the arrays. If they're the same, it compares the name entries. Use that as the callback function for usort.
usort($records, function($x, $y) {
if (count($x) == count($y)) {
$u1 = $x['name'][0];
$u2 = $y['name'][0];
return $u1 < $u2 ? -1 :
($u1 > $u2 ? 1 : 0);
} else {
return count($y) - count($x);
}
});
I have an array that I'm simply trying to order by a score key that contains the value that I'm trying to sort by. The desired results would change the order of the array below to display the index in the following order: [0], [2], [1].
I'm looping through the results which are pulled from a database. I'm creating a key named score and then pushing the $row2 array in to a separate array because if I use mysql_data_seek it gets rid of the score key.
Also it's creating an unwanted key score at the bottom.
How can I best clean this up and make sure the results are ordered high to low as desired?
$my_array = array();
while ($row2 = mysql_fetch_assoc($result2))
{
//score determined here
//$row2['score'] = ...more math, variable is numeric, not a string
array_push($array_page,$row2);
}
Current undesired results...
Array
(
[0] => Array
(
[score] => 7
)
[1] => Array
(
[score] => 2
)
[2] => Array
(
[score] => 4
)
[score] =>
)
Desired results...
Array
(
[0] => Array
(
[score] => 7
)
[2] => Array
(
[score] => 4
)
[1] => Array
(
[score] => 2
)
)
function scoreSort($a, $b){
if($a['score'] == $b['score']) return 0;
return $a['score'] > $b['score'] ? -1 : 1;
}
usort(&$myArray, 'scoreSort');
on php>5.3 you can use inline-functoins:
usort(&$myArray, function($a,$b){ /* ... */ });