This question already has answers here:
Sort array of objects by one property
(23 answers)
Closed 9 years ago.
I have a data like this
array([0] => stdClass Object ( [id] => 1 [title] => AAAA [sentence] => abcdefgh [rank] => 3 ) [1] => stdClass Object ( [id] => 2 [title] => BBBB [sentence] => ijklmn [rank] => 1 ) [3] => stdClass Object ( [id] => 3 [title] => CCC [sentence] => opqrstu [rank] => 2 ));
Show the data:
foreach($data as $d)
{
$title = $d->title;
$sentence = $d->sentence;
$rank = $d->rank;
echo $title. " | " .$sentence. " | " .$rank. "<br>";
}
How to sort it by 'rank'? Thanks for your help.
You can use PHP's usort with a function that uses objects' attribute rank as criteria:
function rank_compare($a, $b) {
return $a->rank - $b->rank;
}
usort($data, 'rank_compare');
More info: http://www.php.net/manual/en/function.usort.php
use php's usort function
usort($array, function($a, $b){
if ($a->rank == $b->rank) return 0;
return ($a->rank > $b->rank)?1:-1;
});
usort takes the array and a comparison function, the comparison function should return 0 if the two parameters are equal in terms of the sort, 1 if the first argument is greater then the second argument and -1 if the first argument is less then the second.
This is where your classes on bubble sorting come in handy. You write yourself a handy little sorting algorithm that takes in an array as an argument, returns an array of sorted stuff... and it's just a couple of for loops. Outer loop is from 0 to the length of the array. Inner loop is from 0 to the length of the array minus the outer loop. And for the inner loop, compare current value to next value - if current value is 'bigger', bubble it up. After the first time through the outer loop, the biggest value is at the top. After the second time through, the second biggest is second from the top. Etc.
Related
There seems to be an undocumented change to how PHP 7 handles equal results in usort functions.
$myArray = array(1, 2, 3);
usort($myArray, function($a, $b) { return 0; });
print_r($myArray);
// PHP 5:
Array
(
[0] => 3
[1] => 2
[2] => 1
)
// PHP 7
Array
(
[0] => 1
[1] => 2
[2] => 3
)
In other words in PHP 7, usort is adding equal values to the end of the array, whereas PHP 5 adds them to the beginning. I can't find any mention of this behaviour.
Is there a way of forcing the PHP 5 behaviour?
From the PHP docs:
If two members compare as equal, their relative order in the sorted array is undefined.
Relying on undefined behavior is a bad idea. There is no way to change the behavior (apart from making the items not equal).
I have the following multidimensional array called $existing_combinations
Array
(
[0] => Array
(
[1] => 6
[2] => 7
[3] => 9
)
[1] => Array
(
[1] => 1
[2] => 21
[3] => 9
)
[2] => Array
(
[1] => 1
[2] => 7
[3] => 9
)
)
I then generate a new array ($new_combination) which has a combination of the same set of values. Example:
Array
(
[1] => 6
[2] => 21
[3] => 9
)
I then test if $new_combination exists in $existing_combinations with the following in the hope that I will end with a unique combination in $new_combination:
foreach($existing_combinations as $key => $combination){
while($new_combination == $combination){
$new_combination = generateNewCombination();
}
}
The problem is that if $new_combination matches an array that is not at index 0, then when I generate a new combination I am at risk of this matching a $combination that has already been tested against (and will not be tested again).
Sorry if this is a simple one but I'm struggling to think of how I can ensure $new_combination will always end up unique.
Any ideas?
Thanks
You can use in_array in this case, because php compares arrays as value. So, the code can be:
while(in_array($new_combination = generateNewCombination(), $existing_combinations));
print_r($new_combination);
I wrote the below before realizing that in_array can also see if an array exists within an array. So you can simply do this:
if (!in_array($new_combination, $existing_combinations)) {
// It's unique.
}
In the below outdated bit, see the note on using sort, if a different sequence of the same numbers isn't considered unique for your purposes.
[ For Entertainment ]
May not be the most elegant way around, but I would simply do this to keep it simple:
$combo_hashes = [];
// Implode the existing combos into strings.
foreach($existing as $vals) {
$combo_hashes[] = implode(':', $vals);
}
Then, all you need to check with your new combo is:
// Check if the "hash"-string already exists.
if (!in_array( implode(':', $new_combo), $combo_hashes)) {
// ... and we're unique.
}
This presumes that you consider [1,3,2] different from [2,1,3]. If they are equivalent (I don't know what your use case is), you should sort($vals); before you generate the check-strings.
Merge all the second level arrays and run array_unique() to get rid of the duplicate values.
This question already has answers here:
Sort a flat, associative array by numeric values, then by non-numeric keys
(8 answers)
Closed 2 years ago.
I've been breaking my head over the following problem.
I've got this array:
[596] => 2
[9] => 2
[358] => 2
[1579] => 1
[156] => 1
[576] => 1
[535] => 1
As you can see, the values are ordered in a descending way, but the keys are random. I would like to keys to be sorted DESC as well though. I've been playing with array_multisort, but I haven't been able to fix the problem with it. The first problem that I encountered was the fact that array_multisort reindexes numeric keys. I changed to keys to a non-numeric variant, namely k596 etc... That made me able to sort the keys, but not like I wanted it to.
[k9] => 2
[k596] => 2
[k358] => 2
[k576] => 1
[k535] => 1
[k1579] => 1
[k156] => 1
The result that I would like to see in the end is:
[k596] => 2
[k358] => 2
[k9] => 2
[k1579] => 1
[k576] => 1
[k535] => 1
[k156] => 1
Is anyone able to help me out here? There must be a simple way to do this, right?
uksort($array, function ($a, $b) use ($array) {
if ($array[$a] != $array[$b]) {
return $array[$a] - $array[$b];
}
return $a - $b;
});
Insert appropriate comparison operations, using simply - here as an example. This is somewhat trickier if you're dependent on PHP < 5.3 and don't have anonymous functions.
Ok this question is a bit more tricky then I thought! Given an array $arry = array('a'=>'hilbert', 'b'=>'noether', 'c'=>'landau');
I would generate a second array containing tuples like this:
$brry = array();
foreach($arry as $key => $value){
$brry[] = array($key,$value);
}
//Now $brry looks like:
//$brry:
// [0] => array('a','hilbert');
// [1] => array('b','noether');
// [2] => array('c','landau');
//now you can easily sort it!
usort($brry, "cmp");
//And then transform it back to the array structure you have before
foreach($brry as $value){
$crry[$value[0]] = $value[1];
}
//with this sorting function cmp:
function cmp($first, $second){
if(strcmp($first[1], $second[1]) != 0){
return strcmp($first[1], $second[1]);
}
else{
return strcmp($first[0], $second[0]);
}
}
The function cmp sorts by strings now so strcmp("192","20") > 0 while this might not be true for integers!
I have an array with the following values
- Array ( [id] => 3 [parent_id] => 2 [name] => Fitness )
- Array ( [id] => 4 [parent_id] => 3 [name] => Why do it)
- Array ( [id] => 5 [parent_id] => 3 [name] => Nutrition)
Id like to query it along the lines of
array_search([parent_id]='3', $array)
and return a list of matching elements. (In this instance it would be id's 4 & 5). I'm not sure if array_search() is the right way to go about this. May attempts are failing at moment.
<?php
function mySearchArr($key, $value, $myBigArr) {
$searchArr = array();
foreach($myBigArr as $smallArr)
if($smallArr[$key] == $value)
$searchArr[] = $smallArr;
return $searchArr
}
$matches = mySearchArr('parent_id', 3, $array);
?>
You could use array_filter with a custom callback
$lookup_id = 3;
$results = array_filter($your_array, function($arr) use ($lookup_id) {
return $your_array['parent_id'] == $lookup_id;
});
This code requires i believe >=PHP5.3, if you have an older version, you will have to implement the callback using either an actual defined function (normal php function), or using create_function
I have two PHP arrays like so:
Array of X records containing the ID
of Wordpress posts (in a particular
order)
Array of Wordpress posts
The two arrays look something like this:
Array One (Sorted Custom Array of Wordpress Post IDs)
Array (
[0] => 54
[1] => 10
[2] => 4
)
Array Two (Wordpress Post Array)
Array (
[0] => stdClass Object
(
[ID] => 4
[post_author] => 1
)
[1] => stdClass Object
(
[ID] => 54
[post_author] => 1
)
[2] => stdClass Object
(
[ID] => 10
[post_author] => 1
)
)
I would like to sort the array of wordpress posts with the order of the ID's in the first array.
I hope this makes sense, and thanks in advance of any help.
Tom
edit: The server is running PHP Version 5.2.14
This should be quite easy using usort, which sorts the array using a user-defined comparison function. The result might look something like this:
usort($posts, function($a, $b) use ($post_ids) {
return array_search($a->ID, $post_ids) - array_search($b->ID, $post_ids);
});
Note that this solution, since it uses anonymous functions and closures, requires PHP 5.3.
One easy solution for this pre-5.3 (the dark ages!) is to do this with a quick loop and then ksort:
$ret = array();
$post_ids = array_flip($post_ids);
foreach ($posts as $post) {
$ret[$post_ids[$post->ID]] = $post;
}
ksort($ret);
You could create a nested looping mechanism to match up the order and ids and rebuild a new post array.
$new_post_array = array();
foreach($id_array as $id) { //loop through custom ordered ids
foreach($post_array as $post) { //for every id loop through posts
if($id == $post->ID){ //and when the custom ordered id matches the post->ID
new_array[] = $post //push the post on the new array
}
}
}
$sortOrderMap = array_flip($postIds);
usort($posts, function($postA, $postB) use ($sortOrderMap) {
return $sortOrderMap[$postA->ID] - $sortOrderMap[$postB->ID];
});
You can simply subtract b from a instead of a from b to sort the other direction