I am trying to sort an array by the length of characters in each value (and perhaps, if possible, in alphabetical order if two values have the same length of characters). For example:
Array ( [0] => this [1] => is [2] => a [3] => bunch [4] => of [5] => words;
I am trying to sort this array to look like:
Array ( [0] => a [1] => is [2] => of [3] => this [4] => bunch [5] => words;
How?
This should do it:
array_multisort(array_map('strlen', $array), $array);
Get the length of each string in an array by mapping strlen() using array_map()
Sort on the string lengths and sort the original array by the string length sorted array using array_multisort()
Looks like others have already answered but I started writing this so I'm going to post it, dang it! :)
You could take a look at usort
$data = ["this", "is", "a", "bunch", "of", "words"];
usort($data, function($a, $b) {
$difference = strlen($a) - strlen($b);
return $difference ?: strcmp($a, $b);
});
I'm using the Elvis operator ?: to just return the difference based on the string lengths if it's not 0. If it is 0, just return the return value of strcmp
You can use a custom sort function for this.
function mycmp($a, $b) {
$cmp = strlen($a) - strlen($b);
if ($cmp === 0)
$cmp = strcmp($a, $b);
return $cmp;
}
usort($array, 'mycmp');
See this:
$myarray = explode(" ", "this is a bunch of words");
usort($myarray, function($a, $b) { return strlen($a) - strlen($b) });
print_r($array);
Explanation: usort sorts in place (i.e. by reference) an array, given a custom comparator. A comparator must return a negative number if the first item should be before the second item, and a positive otherwise. A value of 0 means they are equal regarding the order.
You can add custom criteria, not related to strlen() when the lengths are the same. That's up to you and involves just an additional if block.
It is important to note that the function must define an order relationship, as in math:
criteria(a, b)>0 and criteria(b, c)>0 implies criteria(a, c)>0.
the same applies to the lower-than sign, lower-than-or-equal, greater-than-or-equal, and equal.
criteria(a, b) should have an opposite sign of criteria(b, a).
Another method:
$f = fn($s1, $s2) => strlen($s1) <=> strlen($s2);
usort($a, $f);
https://php.net/language.operators.comparison
Related
I'm using uasort to sort an array that looks like this:
Array
(
[2] => 0
[3] => 0
[4] => 0
)
I'm trying to sort by value, maintaining key association. In addition, I need to keep the original order if the values are the same.
So I'm doing the following:
uasort($arr, array($this, 'mysort'));
function mysort($a, $b){
if($a == $b){
return 0;
}
return ($a < $b) ? -1:1;
}
However, this gives the resulting array:
Array
(
[4] => 0
[3] => 0
[2] => 0
)
Why is the array being effectively reversed?
uasort is not a stable sort, that is, it doesn't maintain the order of equal values.
The manual's notes section contains a stable_uasort.
I've taken a look at a few googles and actually found this stack too: How to sort a date array in PHP
I'ts on the same wave length but i'm not sure i get it clearly. I've read over the phpnet documentation too... As I said, i'm feeling shakey from it.
I have an array:
Array
(
[0] => Array
(
[created] => 2012-06-06 21:26:25
)
[1] => Array
(
[created] => 2012-06-06 21:23:45
)
)
And I basically need to sort this array so that they are in date order.
How does this call back function work for usort? Any examples would be great!
function MySort($a, $b)
{
if ($a['created'] == $b['created']) return 0;
return $a['created'] < $b['created'] ? -1 : 1;
}
then use...
usort($myarray, "MySort");
usort just lets you sort using your own criteria. You can just simply do this:
usort($array, function($a, $b){
$a = strtotime($a['created']);
$b = strtotime($b['created']);
return $a-$b;
});
I have a key => value array:
a => 2
c => 1
b => 3
I tried this:
ksort($result);
arsort($result);
But it doesn't work. I'm trying to sort by key alphabetically a-z and then sort it by value ascending 0-infinity.
so I should get
c => 1
a => 2
b => 3
But those sorts didn't give me what I wanted.
Try using asort() instead of arsort(). arsort() will sort the array in reverse order. Something like this should "work":
$test = array(
'a' => 0,
'b' => 1,
'c' => 2
);
ksort($test);
asort($test);
Mario is correct that this won't work if multiple items contain the same value. Alternatively, you could use uksort() which allows you to define exactly how the array is sorted. For example you could sort two items using their values by default. But if the values are the same sort by their keys.
$test = array(
'a' => 2,
'd' => 1,
'c' => 1,
'b' => 3
);
function cmp($a, $b){
global $test;
$val_a = $test[$a];
$val_b = $test[$b];
if($val_a == $val_b){
return ($a < $b) ? -1 : 1;
}
return ($val_a < $val_b) ? -1 : 1;
}
uksort($test, 'cmp');
I get unexpected results because sorting values that have the same value is unstable.
So what you forgot to mention in your question is that values can occur twice, and you want arrays sorted by values and keys secondarily.
c => 1
a => 2
z => 2
b => 3
There's no function for that in PHP. You could however try to sort by keys first ksort(), and then apply a user-defined function for sorting by value uasort(). In the callback it's important to also implement the $a == $b check and return 0. So the previous key-ordering might not be accidentally altered by +1 or -1 comparison states. (Don't know if that actually works.)
Otherwise you'll have to implement the whole sorting algorithm yourself, possibly separating keys and values in distinct maps.
I want to sort values of an array in alphabetical order in PHP. If all values started with same character then they should be sorted using second character and so on. Ignore case sensitive.
For Example:
before:
values[0] = "programming";
values[1] = "Stackoverflow";
values[2] = "question";
values[3] = "answers";
values[4] = "AA Systems";
after:
values[0] = "AA Systems";
values[1] = "answers";
values[2] = "programming";
values[3] = "question";
values[4] = "Stackoverflow";
I have found some algorithms but I want a way that is fast and with small number of statements. Ignoring case sensitive is special for me. Thanks.
See
natcasesort: http://www.php.net/manual/en/function.natcasesort.php
usort: http://www.php.net/manual/en/function.usort.php with a comparator function that compares strtolower(a) and strtolower(b).
Your example makes two assumptions:
That you are only dealing with simple, 1-dimensional arrays.
That after sorting alphabetically, your index will update so that the first element alphabetically will be assigned key 0 and so forth.
Given those parameters, your simplest solution is to use the array method sort(). With your example:
$values[0] = "programming";
$values[1] = "Stackoverflow";
$values[2] = "question";
$values[3] = "answers";
$values[4] = "AA Systems";
sort($values);
Which will result in the following:
Array {
[0] => AA Systems
[1] => Stackoverflow
[2] => answers
[3] => programming
[4] => question
}
There are other array sorting functions that might be a better fit. For instance, the simple one I use above puts upper-case in front of lower-case, so if you had "security" as an item (all lower-case) it would go after "Stackoverflow" since the upper-case s would take precedence over se vs. st. To sort without case-sensitivity, you could use natcasesort(), which would produce the following with the given array:
Array {
[0] => AA Systems
[1] => answers
[2] => programming
[3] => question
[4] => Stackoverflow
}
As of version 5.4.0, you can just use any of the sort, asort, ksort, etc. functions and pass the SORT_FLAG_CASE flag.
sort( $array, SORT_FLAG_CASE ); // Non-associative array
asort( $array, SORT_FLAG_CASE ); // Associative array
ksort( $array, SORT_FLAG_CASE ); // Associative array, sort by indices
If you've got an older version and aren't ready to update (or can't), you can use natcasesort as others have mentioned, but also the uasort and ksort variants with strcasecmp as the custom function:
natcasesort( $array ); // Non-associative array
uasort( $array, 'strcasecmp' ); // Associative array
uksort( $array, 'strcasecmp' ); // Associative array, sort by indices
You can apply the same concept to any of the other sorting functions.
You can use uasort(): http://php.net/manual/en/function.uasort.php
uasort( $arr, 'strcasecmp' );
The second argument is a function, which compares values. The function must return -1, 0, or 1. Here's a template, which you can use for your custom functions.
function cmp( $a, $b ) {
if ( $a == $b ) return 0;
elseif ( $a > $b ) return 1;
elseif ( $a < $b ) return -1;
}
uasort( $arr, 'cmp' );
After sorting you might want to reset array indexes.
$arr = array_values( $arr );
This is a really esoteric question, but I'm genuinely curious. I'm using usort for the first time today in years, and I'm particularly interested in what exactly is going on. Suppose I've got the following array:
$myArray = array(1, 9, 18, 12, 56);
I could sort this with usort:
usort($myArray, function($a, $b){
if ($a == $b) return 0;
return ($a < $b) ? -1 : 1;
});
I'm not 100% clear about what is going on with the two parameters $a and $b. What are they, and what do they represent. I mean, I could assume that $a represents the current item in the array, but what exactly is this getting compared to? What is $b?
I could increase my array to include strings:
$myArray = array(
array("Apples", 10),
array("Oranges", 12),
array("Strawberries", 3)
);
And run the following:
usort($myArray, function($a, $b){
return strcmp($a[0], $b[0]);
});
And that would sort my child-arrays alphabetically based upon the [0] index value. But this doesn't offer any clarity about what $a and $b are. I only know that the match the pattern that I'm seeking.
Can somebody offer some clarity about what is actually taking place?
The exact definition of $a and $b will depend upon the algorithm used to sort the array. To sort anything you have to have a means to compare two elements, that's what the callback function is used for. Some sorting algorithms can start anywhere in the array, others can start only in a specific part of it so there's no fixed meaning in $a and $b other than they are two elements in the array that have to be compared according to the current algorithm.
This method can be used to shed light upon which algorithm PHP is using.
<?php
$myArray = array(1, 19, 18, 12, 56);
function compare($a, $b) {
echo "Comparing $a to $b\n";
if ($a == $b) return 0;
return ($a < $b) ? -1 : 1;
}
usort($myArray,"compare");
print_r($myArray);
?>
Output
vinko#mithril:~$ php sort.php
Comparing 18 to 19
Comparing 56 to 18
Comparing 12 to 18
Comparing 1 to 18
Comparing 12 to 1
Comparing 56 to 19
Array
(
[0] => 1
[1] => 12
[2] => 18
[3] => 19
[4] => 56
)
From the output and looking at the source we can see the sort used is indeed a quicksort implementation, check for Zend/zend_qsort.c in the PHP source (the linked to version is a bit old, but hasn't changed much).
It picks the pivot in the middle of the array, in this case 18, then it needs to reorder the list so that all elements which are less (according to the comparison function in use) than the pivot come before the pivot and so that all elements greater than the pivot come after it, we can see it doing that when it compares everything to 18 at first.
Some further diagrammatic explanation.
Step 0: (1,19,18,12,56); //Pivot: 18,
Step 1: (1,12,18,19,56); //After the first reordering
Step 2a: (1,12); //Recursively do the same with the lesser, here
//pivot's 12, and that's what it compares next if
//you check the output.
Step 2b: (19,56); //and do the same with the greater
To sort anything you need a means to compare two items and figure out if one comes before the other. This is what you supply to usort. This function will be passed two items from your input array, and returns the order they should be in.
Once you have a means to compare two elements, you can use sort-algorithm-of-your-choice.
If you are unfamiliar, you might like to look at how a simple naive algorithm like bubblesort would use a comparison function.
Behind the scenes, PHP is using a quicksort.
usort() or uasort() have a human-feeling bug on sorted result. See the code segment:
function xxx($a,$b) { if ($a==$b) return 0; else return $a<$b?-1:1; }
$x=array(1=>10,2=>9,3=>9,4=>9,5=>6,6=>38);
uasort($x,'xxx');
print_r($x);
the result is:
Array ( [5] => 6 [4] => 9 [3] => 9 [2] => 9 [1] => 10 [6] => 38 )
Do you see the bug? No? Ok, let me explain it.
The original three '9' elments are in key order: 2,3,4. But in the result, the three '9' elements are now in key order: 4,3,2, i.e. equal-value elements are in reverse key order after sorting.
If the element is only single value, as in above example,it's fine with us. However, if the element is compound value, then it could cause human-feeling bug. See another code segments. We are to sort many points horizontally, i.e. sort them based on ascending x-coordinate value order :
function xxx($a,$b) { if ($a['x']==$b['x']) return 0; else return $a['x']<$b['x']?-1:1; }
$x=array(1=>array('x'=>1, 'v'=>'l'),2=>array('x'=>9, 'v'=>'love'),
3=>array('x'=>9, 'v'=>'Lara'),4=>array('x'=>9, 'v'=>'Croft'),
5=>array('x'=>15, 'v'=>'and'),6=>array('x'=>38, 'v'=>'Tombraider'));
uasort($x,'xxx');
print_r($x);
the result is:
Array ( [1] => Array ( [x] => 1 [v] => l ) [4] => Array ( [x] => 9 [v] => croft )
[3] => Array ( [x] => 9 [v] => Lara ) [2] => Array ( [x] => 9 [v] => love )
[5] => Array ( [x] => 15 [v] => and ) [6] => Array ( [x] => 38 [v] => Tombraider ) )
You see 'I love Lara Croft and Tombraider' becomes 'I Croft Lara love and Tombraider'.
I call it human-feeling bug because it depends on what case you use and how you feel it should be sorted in real world when the compared values are same.