Shortest way to sort that array in PHP? - php

I have this array:
array
0 =>
array
'action_operator' => string 'by_fixed' (length=8)
'action_amount' => string '10.0000' (length=7)
'sort_order' => string '0' (length=1)
1 =>
array
'action_operator' => string 'by_percent' (length=10)
'action_amount' => string '10.0000' (length=7)
'sort_order' => string '1' (length=1)
...
I want to sort that according to the sort_order key starting with the lowest (0 in this case). I know I can iterate and so on, but whats the shortest code to achieve that?
Thanks :)

<?php
usort( $aData, function( $a, $b ) {
return ($a['sort_order'] < $b['sort_order'] ? 1 : -1);
} );
With PHP7 you should be able to use the spaceship operator:
usort( $aData, function( $a, $b ) {
return $a['sort_order'] <=> $b['sort_order'];
} );

A one-liner using usort:
usort($array, function($a, $b) { return $a['sort_order'] - $b['sort_order']; });

Related

PHP asort for sorting array items by values ASC?

It is strange with asort, I want to sort the items in an array by their value,
$items = Array ( "1" => 10 , "11" => 10, "22" => 10 );
// Sort an array and maintain index association.
asort($items);
var_dump($items);
So since all values are the same, then asort shouldn't doing anything (I assume), but the result I get,
array (size=3)
22 => string '10' (length=2)
11 => string '10' (length=2)
1 => string '10' (length=2)
It reverses the order!? Why?
what I want (I think it should be like this),
array (size=3)
1 => string '10' (length=2)
11 => string '10' (length=2)
22 => string '10' (length=2)
Any ideas?
EDIT:
I tried with this below,
// Comparison function
private function cmp($a, $b) {
if ($a == $b) {
return 0;
}
return ($a < $b) ? -1 : 1;
}
...
// Sort an array and maintain index association.
uasort($items, array($this, "cmp"));
But I still get the same 'error' result....
Since the version 4.1.0 PHP sort is not stable due to sorting algorithm, which cannot take into account both value and key. You have to use your own implementation of comparison considering key in case of equal values. For example you can modify original array values into (key, value) pairs, sort array and transform it into single dimensional back.
$items = ["1" => 10, "11" => 10, "22" => 10];
$callback = function ($a, $b) use ($callback) {
$result = $a['value'] - $b['value'];
if ($result == 0) {
$result = $a['key'] - $b['key'];
}
return $result;
};
array_walk($items, function (&$value, $key) {
$value = ["key" => $key, "value" => $value];
});
usort($items, $callback);
$items = array_combine(array_column($items, 'key'), array_column($items, 'value'));
print_r($items);

Sort PHP array by date

I have a bunch of files that are in an array
im(month)(day)(year)
im01012007
im01022006
im01022012
im01032011
im01042010
im01042012
im01052009
im01052011
im01062012
im01072008
im01072011
etc..
is there a way to sort the array so that it sorted by year then month then day?
You can try use usort
$string = "im01012007.jpg,im01022006.jpg,im01022012.jpg,im01032011.jpg,im01042010.jpg,im01042012.jpg,im01052009.jpg,im01052011.jpg,im01062012.jpg,im01072008.jpg,im01072011.jpg";
$array = explode(",", $string); // rebulding your array ;
var_dump($array);
usort($array, function ($a, $b) {
$a = DateTime::createFromFormat("mdY", substr(pathinfo($a, PATHINFO_FILENAME), 2));
$b = DateTime::createFromFormat("mdY", substr(pathinfo($b, PATHINFO_FILENAME), 2));
return ($a == $b) ? 0 : (($a < $b) ? - 1 : 1);
});
var_dump($array);
Output
Before
array
0 => string 'im01012007.jpg' (length=14)
1 => string 'im01022006.jpg' (length=14)
2 => string 'im01022012.jpg' (length=14)
3 => string 'im01032011.jpg' (length=14)
4 => string 'im01042010.jpg' (length=14)
5 => string 'im01042012.jpg' (length=14)
6 => string 'im01052009.jpg' (length=14)
7 => string 'im01052011.jpg' (length=14)
8 => string 'im01062012.jpg' (length=14)
9 => string 'im01072008.jpg' (length=14)
10 => string 'im01072011.jpg' (length=14)
After
array
0 => string 'im01022006.jpg' (length=14)
1 => string 'im01012007.jpg' (length=14)
2 => string 'im01072008.jpg' (length=14)
3 => string 'im01052009.jpg' (length=14)
4 => string 'im01042010.jpg' (length=14)
5 => string 'im01032011.jpg' (length=14)
6 => string 'im01052011.jpg' (length=14)
7 => string 'im01072011.jpg' (length=14)
8 => string 'im01022012.jpg' (length=14)
9 => string 'im01042012.jpg' (length=14)
10 => string 'im01062012.jpg' (length=14)
Yes there is. Convert it to a sensible format first.
I suggest using PHP's DateTime class and keeping all your dates as DateTime objects while you're in the PHP program.
If you don't want to do that, here's a function to sort them in as-is.
usort($myDates, function($a, $b) {
$aBits = array_chunk($a,2);
$bBits = array_chunk($a,2);
$aDate = $aBits[3].$aBits[4].$aBits[2].$aBits[1];
$bDate = $aBits[3].$aBits[4].$aBits[2].$aBits[1];
return ($aDate < $bDate) ? -1 : 1;
});
Hope that helps.
Use substr() and divide your string into parte (day,month,year). Then You can sort them.
No built in function will do this out of the box, i would use usort like this:
usort($files, function($a, $b) {
return strcmp(preg_replace('/^.*(\d{2})(\d{2})(\d{4})$/', '$3$1$2', $a), preg_replace('/^.*(\d{2})(\d{2})(\d{4})$/', '$3$1$2', $b));
});
This will sort oldest to newest. Use krsort to sort newest to oldest.
$files = array();
if ($handle = opendir('/path/to/files')) {
while (false !== ($entry = readdir($handle))) {
if ($entry != "." && $entry != "..") {
$y = substr($entry, 6, 4);
$m = substr($entry, 2, 2);
$d = substr($entry, 4, 2);
$files[$y . $m . $d] = $entry;
}
}
closedir($handle);
}
ksort($files);
I used these PHP Manual entries to write this solution:
readdir
ksort
substr

PHP sorting 3 dimensional array

I know this would be an easy one but I don't get it. All answered I found on the net was... too complex to me, maybe.
Here is my typical array:
array(
(int) 0 => array(
'Conversation' => array(
'id' => '1',
'created' => '2012-08-04 00:00:00'
),
'ConversationUser' => array(
(int) 0 => array(
'id' => '1'
),
(int) 1 => array(
'id' => '2'
)
)
),
(int) 1 => array(
'Conversation' => array(
'id' => '2',
'created' => '2012-08-01 00:00:00'
),
'ConversationUser' => array(
(int) 0 => array(
'id' => '1'
),
(int) 1 => array(
'id' => '2'
)
)
));
I want to sort my data with ['Conversation']['created'] date, asc or desc.
Any simple answer ? :P
P.S. I can't use MYSQL sort, I retrieve the data one by one and create that array.
Use usort() :
usort($your_array, function($a, $b){
$a = strtotime($a['Conversation']['created']);
$b = strtotime($b['Conversation']['created']);
if ($a == $b) {
return 0;
}
return ($a > $b) ? -1 : 1;
});
You can use array_multisort to do this:
// $data is your array from the example
// first obtain the rows for sorting
$sortkeys = array();
foreach ($data as $row) {
$sortkeys[] = $row['Conversation']['created'];
}
// sort $data according to $sortkeys
array_multisort($sortkeys, $data);
var_dump($data);
You should have a look to uksort() and usort() functions, which let you customize the way arrays are sorted.
Either the solution is simple or complex, remember what Einstein said once: "Things should be always done as simple as possible, but never simpler than they really are".
If you have some trouble with these functions, we can give you further clues ;-)
You can use usort() (or, to maintain index association, uasort(). Example: (assumes your array is $arr):
usort($arr, function($a, $b) {
return
preg_replace('/\D/', '', $b['Conversation']['created'])
>
preg_replace('/\D/', '', $a['Conversation']['created']);
});
That will sort descending. Change > to < for ascending.

How to sort associative array using sub-field of contained associative arrays in PHP?

How can I sort an associative array by one of its values?
For example:
$arr = array(
'ted' => array( 'age' => 27 ),
'bob' => array( 'age' => 18 ),
'jay' => array( 'age' => 24 )
);
$arr = ???
foreach ($arr as $person)
echo $person['age'], ', ';
So that the output is:
18, 24, 27
This is an oversimplified example just to demonstrate my question.
I still require that $arr is an associative array.
The uasort() function allows you to specify a callback function, which will be responsible of doing the comparison between two elements -- so, should do just well, if you implement the proper callback function.
Here, you'd have to implement a callback function that will receive two arrays -- and compmare the age item :
function callback($a, $b) {
if ($a['age'] > $b['age']) {
return 1;
} else if ($a['age'] < $b['age']) {
return -1;
}
return 0;
}
Using that function in the following portion of code :
$arr = array(
'ted' => array( 'age' => 27 ),
'bob' => array( 'age' => 18 ),
'jay' => array( 'age' => 24 )
);
uasort($arr, 'callback');
var_dump($arr);
You would get you this resulting array :
array
'bob' =>
array
'age' => int 18
'jay' =>
array
'age' => int 24
'ted' =>
array
'age' => int 27
This is a classical example where PHP 5.3 anonymous functions come in handy:
uasort($arr, function($a, $b) {
return $a['age'] - $b['age'];
});
The $a['age'] - $b['age'] is a small trick. It works because the callback function is expected to return a value < 0 is $a is smaller than $b and a value > 0 if $a is bigger than $b.
Since you're sorting on a value inside a sub array, there's not a built-in function that will do 100% of the work. I would do a user-defined sort with:
http://www.php.net/manual/en/function.uasort.php
Here's an example comparison function that returns its comparison based on this value in the nested array
<?php
// Comparison function
function cmp($left, $right) {
$age1 = $left['age'];
$age2 = $right['age'];
if ($age1 == $age2) {
return 0;
}
return ($age1 < $age2) ? -1 : 1;
}
uasort($array, 'cmp');
http://www.php.net/manual/en/array.sorting.php
This particular case will involve using one of the sort methods that use a callback to sort
You're not just sorting an associative array, you're sorting an associative array of associative arrays ;)
A uasort call is what you're after
uasort($array, function ($a, $b) {
if ($a['age'] === $b['age']) {
return 0;
}
return $a['age'] > $a['age'] ? 1 : -1;
});

How do I sort a multi-dimensional array by value?

I have an array as following and I want to order that array by the value of the key "attack". First keys of the arrays (15, 13, 18) are ID of some certain item from database, so I don't want these keys to be changed when the array is sorted. Any help would be greatly appreciated.
This is the array:
$data = array(
'15' => array(
'attack' => '45', 'defence' => '15', 'total' => '10'
),
'13' => array(
'attack' => '25', 'defence' => '15', 'total' => '10'
),
'18' => array(
'attack' => '35', 'defence' => '15', 'total' => '10'
)
);
Use uasort():
This function sorts an array such that array indices maintain their correlation with the array elements they are associated with, using a user-defined comparison function.
This is used mainly when sorting associative arrays where the actual element order is significant.
Example:
function cmp($a, $b) {
if ($a['attack'] == $b['attack']) {
return 0;
}
return ($a['attack'] < $b['attack']) ? -1 : 1;
}
uasort($data, 'cmp');
If the values are always strings, you can also use strcmp() in the cmp() function:
function cmp($a, $b) {
return strcmp($a['attack'], $b['attack']);
}
Update:
To sort in descending order you just have to change the return values:
return ($a['attack'] < $b['attack']) ? 1 : -1;
// ^----^
or to pick up #salathe's proposal:
return $b['attack'] - $a['attack'];
Simply use array_multisort
foreach ($data as $key => $row) {
$attack[$key] = $row['attack'];
}
// Sort the data with attack descending
array_multisort($attack, SORT_DESC, $data);
Hope this helps.
$result = [];
foreach ($data as $key => $value) {
$result[$key] = $value;
asort($result[$key]);
}
print_r($result);
Hope this helps !!!

Categories