German Geek schreef:
> Remember we have copy-on-write in PHP.
>
> Beat this :P :
for speed it's way faster, slight issue though, it won't
give the expected output for arrays that contain the same
value more than once. not difficult to fix that,
below a new version of the test script with both your
original variant (timeSort4()) and a version that doesn't mislay
duplicates (timeSort5()). both take half the time to run roughly ... nice :-)
<?php
// TEST
ini_set("date.timezone", "Europe/Amsterdam");
$iter = 10000;
$time = array(
array("1:30pm", "7:30am", "12:30pm"),
array("1:30pm", "7:30am", "12:30pm", "4:45pm", "8:15am", "11:00pm"),
array("1:30pm", "7:30am", "12:30pm", "4:45pm", "8:15am", "11:00pm",
"4:30am", "6:45am", "12:00pm"),
);
foreach ($time as $t)
testIt($t, $iter);
// FUNCS
function sortTime1($in_times)
{
$time = array();
foreach ($in_times as $t)
$time[] = strtotime($t);
sort($time);
$sort_time = array();
foreach ($time as $t)
$sort_time[] = date("g:ia", $t);
return $sort_time;
}
function timeSort2($in)
{
static $time = null;
if (!$time)
$time = time();
$now = array_fill(0, count($in), $time);
$out = array_map("strtotime", $in, $now);
array_multisort($out, SORT_NUMERIC, SORT_ASC, $in);
return $in;
}
function timeSort3($a, $b)
{
static $now = null;
if (!$now)
$now = time();
$a = strtotime($a, $now);
$b = strtotime($b, $now);
if ($a == $b)
return 0;
return $a < $b ? -1 : 1;
}
function timeSort4($ar)
{
$stamps = array();
foreach ($ar as $timeString)
$stamps[strtotime($timeString)] = $timeString;
ksort($stamps);
return array_values($stamps);
}
function timeSort5($ar)
{
$stamps = array();
foreach ($ar as $ts)
if (isset($stamps[$ts]))
$stamps[strtotime($ts)][1]++;
else
$stamps[strtotime($ts)] = array($ts, 1);
ksort($stamps);
$ar = array();
foreach ($stamps as $data)
for ($i = 0; $i < $data[1]; $i++)
$ar[] = $data[0];
return $ar;
}
function testIt($time, $iter)
{
echo "\nNo. of array items = ", count($time), ", no of iterations =
$iter\n-------\n";
$s = microtime(true);
for ($i = 0; $i < $iter; $i++)
timeSort2($time);
$e = microtime(true);
echo "timeSort1() ran for ".round($e-$s, 6)." seconds \n";
$s = microtime(true);
for ($i = 0; $i < $iter; $i++)
timeSort2($time);
$e = microtime(true);
echo "timeSort2() ran for ".round($e-$s, 6)." seconds \n";
$s = microtime(true);
for ($i = 0; $i < $iter; $i++)
usort($time, "timeSort3");
$e = microtime(true);
echo "timeSort3() ran for ".round($e-$s, 6)." seconds \n";
$s = microtime(true);
for ($i = 0; $i < $iter; $i++)
timeSort4($time);
$e = microtime(true);
echo "timeSort4() ran for ".round($e-$s, 6)." seconds \n";
$s = microtime(true);
for ($i = 0; $i < $iter; $i++)
timeSort5($time);
$e = microtime(true);
echo "timeSort5() ran for ".round($e-$s, 6)." seconds \n";
}
?>
> <?php
>
> $timeArray = array(/* your string time data */);
>
> function timeStamps($ar) {
> $stamps = array();
> foreach ($ar as $timeString) {
> $stamps[strtotime($timeString)] = $timeString;
> }
> return $stamps;
> }
>
> function sortTime(&$ar) {
> $timeStampAr = timeStamps($ar);
> ksort($timeStampAr); // since the keys are integers, timestamps ksort
> would do the right thing
> $ar = array_values($timeStampAr);
> return $ar; //dont really need this but just in case someone prefers to
> use
> //it differently or needs a copy
> }
>
> sortTime($timeArray);
>
> /* this way the strtotime function is only applied once to each time string
> which is probably the most expensive. And ksort uses the sort algorithm that
> the PHP core programmers regard as the most efficient. I believe quick sort.
> CODE NOT TESTED :P might have minor mistakes but i doubt it :P.*/
>
> ?>
> Tim-Hinnerk Heuer
>
> http://www.ihostnz.com
> Fred Allen - "California is a fine place to live - if you happen to be an
> orange."
>
> 2009/2/16 Jochem Maas <[email protected]>
>
>> Shawn McKenzie schreef:
>>> Shawn McKenzie wrote:
>> ...
>>
>>>>> Not tested:
>> no shit.
>>
>>>>> function time_sort($a, $b)
>>>>> {
>>>>> if (strtotime($a) == strtotime($b)) {
>>>>> return 0;
>>>>> }
>>>>> return (strtotime($a) < strtotime($b) ? -1 : 1;
>>>>> }
>>>>>
>>>>> usort($time, "time_sort");
>>>>>
>>>> Well, I just thought, since the strtotime() uses the current timestamp
>>>> to calculate the new timestamp, if you only give it a time then the
>>>> returned timestamp is today's date with the new time you passed. If you
>>>> had a large array and the callback started at 23:59:59 then you could
>>>> end up with some times from the date it started and some from the next
>>>> day, which of course would not be sorted correctly with respect to times
>>>> only. So, this might be better (not tested):
>>>>
>> ditto (as in nice syntax error).
>>
>>>> function time_sort($a, $b)
>>>> {
>>>> static $now = time();
>>>>
>>>> if (strtotime($a, $now) == strtotime($b, $now)) {
>>>> return 0;
>>>> }
>>>> return (strtotime($a, $now) < strtotime($b, $now) ? -1 : 1;
>>>> }
>>>>
>>>>
>>> Your best bet above.
>> and G.W.Bush is a socialist.
>>
>> I did a little test, the ultra-fast version offered by McKenzie
>> is really great as long as your array of time strings aren't ever
>> going to be longer than say 3-4 items (with the caveat that you
>> don't use a second argument to strtotime() ... if you do then
>> even with 3 items it's substantially slower).
>>
>> for any reasonable number of items my tests show tedd's version
>> pisses on McKenzies from a great height (note that I actually
>> optimized Mckenzies variant by halfing the number of calls to
>> strtotime()).
>>
>> I added a third variant, as a sort of control, which runs pretty
>> much on par with tedd's version but uses rather less LOC
>> (tedd you might like it as a little example of using array_multisort(),
>> i.e. a way of avoiding writing the double foreach loop in this case)
>>
>> tedd's variant: sortTime1()
>> McKenzie's variant: sortTime2()
>> my variant: sortTime3()
>>
>> sample output from one of my test runs:
>> ===============================================================
>> ===============================================================
>> No. of array items = 3, no of iterations = 10000
>> -------
>> timeSort1() ran for 1.306011 seconds
>> timeSort2() ran for 1.337358 seconds
>> timeSort3() ran for 1.742724 seconds
>>
>> No. of array items = 6, no of iterations = 10000
>> -------
>> timeSort1() ran for 2.647697 seconds
>> timeSort2() ran for 2.475791 seconds
>> timeSort3() ran for 7.268916 seconds
>>
>> No. of array items = 9, no of iterations = 10000
>> -------
>> timeSort1() ran for 3.891894 seconds
>> timeSort2() ran for 3.960463 seconds
>> timeSort3() ran for 18.440713 seconds
>>
>>
>>
>>
>> the test script:
>> ===============================================================
>> ===============================================================
>> <?php
>> // TEST
>> ini_set("date.timezone", "Europe/Amsterdam");
>>
>> $iter = 10000;
>> $time = array(
>> array("1:30pm", "7:30am", "12:30pm"),
>> array("1:30pm", "7:30am", "12:30pm", "4:45pm", "8:15am", "11:00pm"),
>> array("1:30pm", "7:30am", "12:30pm", "4:45pm", "8:15am", "11:00pm",
>> "4:30am", "6:45am", "12:00pm"),
>> );
>>
>> foreach ($time as $t)
>> testIt($t, $iter);
>>
>>
>> // FUNCS
>>
>> function sortTime1($in_times)
>> {
>> $time = array();
>> foreach ($in_times as $t)
>> $time[] = strtotime($t);
>>
>> sort($time);
>>
>> $sort_time = array();
>> foreach ($time as $t)
>> $sort_time[] = date("g:ia", $t);
>>
>> return $sort_time;
>> }
>>
>> function timeSort2($in)
>> {
>> static $time = null;
>>
>> if (!$time)
>> $time = time();
>>
>> $now = array_fill(0, count($in), $time);
>> $out = array_map("strtotime", $in, $now);
>> array_multisort($out, SORT_NUMERIC, SORT_ASC, $in);
>>
>> return $in;
>> }
>>
>> function timeSort3($a, $b)
>> {
>> static $now = null;
>>
>> if (!$now)
>> $now = time();
>>
>> $a = strtotime($a, $now);
>> $b = strtotime($b, $now);
>> if ($a == $b)
>> return 0;
>>
>> return $a < $b ? -1 : 1;
>> }
>>
>> function testIt($time, $iter)
>> {
>> echo "\nNo. of array items = ", count($time), ", no of iterations =
>> $iter\n-------\n";
>>
>> $s = microtime(true);
>> for ($i = 0; $i < $iter; $i++)
>> timeSort2($time);
>> $e = microtime(true);
>> echo "timeSort1() ran for ".round($e-$s, 6)." seconds \n";
>>
>> $s = microtime(true);
>> for ($i = 0; $i < $iter; $i++)
>> timeSort2($time);
>> $e = microtime(true);
>> echo "timeSort2() ran for ".round($e-$s, 6)." seconds \n";
>>
>> $s = microtime(true);
>> for ($i = 0; $i < $iter; $i++)
>> usort($time, "timeSort3");
>> $e = microtime(true);
>> echo "timeSort3() ran for ".round($e-$s, 6)." seconds \n";
>> }
>>
>> --
>> PHP General Mailing List (http://www.php.net/)
>> To unsubscribe, visit: http://www.php.net/unsub.php
>>
>>
>
--
PHP General Mailing List (http://www.php.net/)
To unsubscribe, visit: http://www.php.net/unsub.php