I have this array in PHP:
foreach($rss_items as $item) :
$contenu[] = array (
"auteur" => $author,
"date" => $item->get_date(),
"contenu" => $item->get_content()
);
At the end, my array is composed of 6 parts, which everyone contains the 3 variable above.
My question is: How can I sort the array by date and using the strtotime because it's easier to sort with this function.
strtotime($item->get_date());
Use usort to sort based on your own callback function.
usort($contenu, function($a, $b){
$aSort = strtotime($a['date']);
$bSort = strtotime($b['date']);
if($aSort === $bSort) return 0;
return ($aSort < $bSort) ? -1 : 1;
});
NOTE: This will only work in PHP 5.3+. If you have 5.2 or lower, you can use create_function.
usort($contenu, create_function('$a, $b','
$aSort = strtotime($a["date"]);
$bSort = strtotime($b["date"]);
if($aSort === $bSort) return 0;
return ($aSort < $bSort) ? -1 : 1;
'));
Related
This question already has answers here:
How to Sort a Multi-dimensional Array by Value
(16 answers)
Closed 9 years ago.
My array:
$MY_ARRAY =
Array
(
[0] => Array
(
[0] => 2861
[1] => Array
(
[start_month] => 6
[start_year] => 1970
[end_month] => 12
[end_year] => 1990
[experience_info] => "Practically a random string"
)
)
)
And I would like to sort $MY_ARRAY direct children by their inner contents,
ideally in an order of start_year, start_month, end_year, end_month. I guess I could use the array_multisort() somehow, but I don't know how. Does anyone know how to deal with this?
Thanks.
EDIT: As it showed up, the solution was nice and simple, what I didnt know is that during the comparsion in callback-compare-function you can go to the deeper structure - so if your deeper than lvl-1 indexes remains always the same (my case) that is how to do it :)
For this purpose you can use uasort function:
function compare_callback($arr1, $arr2) {
$start_year1 = $arr1[1]['start_year'];
$start_year2 = $arr2[1]['start_year'];
$start_month1 = $arr1[1]['start_month'];
$start_month2 = $arr2[1]['start_month'];
$end_year1 = $arr1[1]['end_year'];
$end_year2 = $arr2[1]['end_year'];
$end_month1 = $arr1[1]['end_month'];
$end_month2 = $arr2[1]['end_month'];
return ($start_year1 === $start_year2)
? (($start_month1 === $start_month2)
? (($end_year1 === $end_year2)
? (($end_month1 === $end_month2)
? 0
: (($end_month1 < $end_month2) ? -1 : 1))
: (($end_year1 < $end_year2) ? -1 : 1))
: ($start_month1 < $start_month2) ? -1 : 1)
: (($start_year1 < $start_year2) ? -1 : 1);
}
uasort($array, 'compare_callback');
You can use PHP's usort function and supply your own comparison function. Like this:
function cmp($a, $b)
{
if ($a[1]['start_year'] == $b[1]['start_year'])
{
// You can further do tests for start_month, etc in here if start_years are equal
return 0;
}
return ($a[1]['start_year'] > $b[1]['start_year']) ? 1 : -1;
}
usort($MY_ARRAY, "cmp");
The above will sort your array by start_year. I haven't tested the code, but it should work.
Do something like the following :
$newArray = array();
foreach($MY_ARRAY as $value) {
$newArray[] = $value[1];
}
multi_sort($newArray, $MY_ARRAY);
I have a PHP array with keys that contain a year and week number like so:
year-week
Using the built in ksort function it's returning them like so:
ksort($array);
2011-21
2011-3
2011-44
2011-45
Is it possible to have them sorted numerically like so:
2011-3
2011-21
2011-44
2011-45
If you are using PHP >= 5.4 use ksort($array, SORT_NATURAL);
Use uksort to sort the keys, and in the callback use, strnatcmp.
uksort($array, function($a,$b){
return strnatcmp($a,$b);
});
You can use natsort
$a = array_keys($myarray);
// $a now has
// array('2011-21', '2011-3', '2011-45', '2011-44');
natsort($a);
This prints
2011-3
2011-21
2011-44
2011-45
You can then use the $a array as a reference to each element of the array that holds the data (in the example above $myarray)
You can use ksort with natural flag. (Only PHP 5.4+ supports)
ksort($array, SORT_NATURAL);
You'll get the result you want if you format them with a 2 digit week. Something more like 2011-03. See sprint_f().
I see much simpler solutions are available, but here was my initial thought:
function cmp($a, $b) {
$comp1 = explode('-', $a);
$comp2 = explode('-', $b);
$year1 = (int) $comp1[0];
$year2 = (int) $comp2[0];
$week1 = (int) $comp1[1];
$week2 = (int) $comp2[1];
if ($year1 == $year2 && $week1 == $week2) {
return 0;
} elseif ($year1 == $year2) {
return ($week1 < $week2) ? -1 : 1;
} else {
return ($year1 < $year2) ? -1 : 1;
}
}
$array = array('2011-21', '2011-3', '2011-44', '2011-45');
uasort($array, 'cmp');
I am sure this has been answered somewhere before but I couldn't find the answer to this exact case...
I know I can use the usort function, but can't figure out the logic to do what I want eventhough it's relatively simple
I have a dynamic area being generated as such:
$details[$pageYear][$pageMonth][] = array(
"id" => $page['id'],
"title" => $page['title']
);
I want the array $details to be eventually sorted descending by year, then by month
the month value is string (january, february, march, etc... and not numeric), which seems to be my main issue (how to sort the month 'strings' by actual order and not letter order)
any help would be greatly appreciated
sorry if this turns out to be a duplicate
can you use uasort whit this callback?
<?php
function cmp_month_strings($a_string, $b_string)
{
$a_value = strtotime("{$a_string} 2000");
$b_value = strtotime("{$b_string} 2000");
if($a_value == $b_value)
return 0;
else if($a_value < $b_value)
return -1;
else
return 1;
}
?>
To sort by key, you need uksort
Some similar way:
uksort($details, function($a, $b) {
return ($a < $b) ? -1 : 1;
});
foreach ($details as &$year) {
uksort($year, function($a, $b) {
$montha = (int) date('m', strtotime("{$a} 1 2000"));
$monthb = (int) date('m', strtotime("{$b} 1 2000"));
return ($montha < $monthb) ? -1 : 1;
});
}
Ok, first of all, I'm not even sure the title is right, if so, I'm sorry.
I have this loop here which is the result of a MongoDB query:
foreach($cursor as $obj) {
$monster = $obj["type"];
$strenght = $obj["strenght"];
$obj["value"] = rand(5, 15);
}
now, I have put rand there to signify that value changes for each iteration. Now i want that this array, when is printed, is ordered by that $obj["value"], and be able to chose if ascending or descending.
ok, I have tried this
foreach($cursor as $obj) {
$type = $obj["monster"];
$strenght = $obj["strenght"];
$obj["value"] = rand(5, 15);
$newarr[] = $obj;
}
usort($newarr, "cmp");
function cmp($a, $b)
{ return $b['value'] < $a['value']; }
foreach ($newarr as $obj)
{
echo $obj['value'] . $obj['type'] . "<br/>";
}
As I expected, the
$obj["value"] = rand(5, 15);
does not get lost at every iteration in fact, the $newarr contains that value, the problem is that it does not sort them at all. The items are printed in the same order as they were put inside the array. Any help?
Thanks
function mysort ($arr,$d='asc') {
global $dir;
$dir = $d;
uasort($arr, 'cmp');
return ($arr);
}
function cmp ($a, $b) {
global $dir;
if($a['value'] == $b['value']) return 0;
else {
if(strtolower($dir) == 'asc')
return ($a['value'] > $b['value']) ? 1 : -1;
else if(strtolower($dir) == 'disc')
return ($a['value'] > $b['value']) ? -1 : 1;
}
}
print_r(mysort($obj, 'disc'));
ACCORDING TO YOUR UPDATE
try this cmp()
function cmp($a, $b) {
if($a['value'] == $b['value']) return 0;
return $a['value'] > $b['value'] ? 1 : -1;
}
First of all, by doing $obj["value"] = rand(..) you are assigning same array variable with different values multiple times. By the end of the loop, the variable will only contain one value.
You probably were trying to do this
$obj["value"][] = rand(5, 15); //This adds a new random item to the array contained in $obj['value'] each time
When you have an array items, you can sort them by using sort()[ascending] function rsort()[Descending[
$sorted = sort($obj["value"]);
print_r($sorted);
You loose this value
$obj["value"] = rand(5, 15);
at each iteration i guess. Check this link for php foreach loop:
PHP FOREACH
For sorting u can use sort function of php:
PHP SORT
Your foreach will not really generate anything useful. So I created an example array to illustrate the principle:
$array = array(
array(
'type' => 'type a',
'strength' => '10',
'value' => '12',
),
array(
'type' => 'type b',
'strength' => '12',
'value' => '15',
),
array(
'type' => 'type c',
'strength' => '11',
'value' => '6',
),
);
Now you want this multi dimensional array to be sorted by the value, so you would have a list if it was descending order, of type b, type a and then type c.
The function you are looking for is array_multisort(). Here a sample how to use it on this particular instance. First you need to create that sorter array for the function to do it's job. Then just use multisort and you are done.
$sorter = array();
foreach ($array as $key => $row) {
$sorter[$key] = $row['value'];
}
array_multisort($sorter, SORT_DESC, $array);
Now $array has been resorted according to the specifications. Use SORT_ASC to reverse the sorting.
Added code: Just for sake of completeness, here is your foreach code that should technically create what you wanted to in the first place:
$array = array();
foreach($cursor as $obj) {
$row = array();
$row['type'] = $obj['type'];
$row['strength'] = $obj['strenght'];
$row['value'] = rand(5, 15);
$array[] = $row;
}
Also you have a typo in strength :)
Since you are working with integer values, you can simply use this:
usort($newarr, "cmp");
function cmp($a, $b) {
return $b['value'] - $a['value'];
}
It will sort your keys in descending order, if you want to change that to ascending, swap $a and $b.
Sorting functions generally expect the compare function to return a value of 0 if the items are the same, <0 if the first argument is less than the second (whatever less means in the particular case) and >0 if the first argument is greater than the second.
With integer values this can simply be written as $a - $b or $b - $a.
I have a .txt file that looks like this:
john 1000
mike 8393
tom 1000
bob 233
roger 2
daniel 233
... ...
I need to put every line into array and sort by number size without losing what name goes with what number.
Also some numbers are repeating through the file.
Finally I want to echo elements of an array sorted by number size.
You could break each line into an array of integers and strings (split your current strings on the space) and then sort the array using ksort (assuming the key is the integer) and there you go!
You can of course alternatively use a more robust sort, but this will get you there.
You can then print it by using print_r to print the human readable version of the array
http://php.net/manual/en/array.sorting.php
http://php.net/manual/en/function.print-r.php
If you're running php 5.3+
$fileLines = explode("\n", $fileContents);
usort($fileLines, function($a, $b) {
$aNumber = (int)substr($a, strpos($a, ' ')+1);
$bNumber = (int)substr($b, strpos($b, ' ')+1);
if($aNumber === $bNumber) {
return 0;
}
return $aNumber > $bNumber ? 1 : -1;
});
If you're running a lower version, convert the function into a global function and provide the name as a callback string.
usort($fileLines, 'sortlines');
function sortlines($a, $b) {
$aNumber = (int)substr($a, strpos($a, ' ')+1);
$bNumber = (int)substr($b, strpos($b, ' ')+1);
if($aNumber === $bNumber) {
return 0;
}
return $aNumber > $bNumber ? 1 : -1;
}
then
var_dump($fileLines);
You can go three ways:
1.Create two-dimensional array with numeric indexes and sort it with usort(); and lambda function
$list = array(array('name' => 'john', 'number' => 1000),
array('name' => 'mike', 'number' => 8393),
array('name' => 'tom', 'number' => 1000)
);
$by = 'number';
usort($list, function($first, $second) use ($by)
{
if ($first[$by] > $second[$by] { return 1; }
elseif (first[$by] < $second[$by]) { return -1; }
return 0;
}
);
2.Create array with indexes as names and sort it with sort();
$list = array('john' => 1000,
'mike' => 8393,
'tom' => 1000
);
sort($list);
3.Create array with indexes as numbers and sort it with ksort();
$list = array(1000 => 'john',
8393 => 'mike',
1000 => 'tom'
);
ksort($list);
If you choose first way you can address the element as
$list[0][name] = 'bob'
$list[1][number] = 1000;
Second
$list['john'] = 1001;
Third
$list[1000] = 'bob';
In last two ways you should use foreach to go through array
Use
print_r($list);
or
var_dump($list);
to print the array, or create your own code
P.S. Don't forget thar calling usort with lambda function is PHP 5.3 way, if you use earlier version of PHP, you should use discrete function