[Closed] Sorting dates
So, I have an array of dates in this format: 4 digit year, 2 digit month, 2 digit date
ex: #(2011.01.15, 2009.01.15, 2011.05.16, 2010.05.22)
- Does max have a built in function to sort these newest to oldest?
- If not, would this algorithm basically be a filterString by period, then quicksort on the years, then a quicksort on the months, then a quicksort on the days?
- If not, what would be the fastest way to soft these dates?
Thanks!
In this specific format, regular string-based sorting should work.
sort #("2011.01.15", "2009.01.15", "2011.05.16", "2010.05.22")
--> #("2009.01.15", "2010.05.22", "2011.01.15", "2011.05.16")
actually, after sorting, i needed the array to be flipped from oldest first to newest first.
so here’s what i wrote to do that, in case any one else needs such code
and also, if you know of a better way to do this – I’d like to know
--flip the array
local mySortedArray = #()
while myFilteredNames.count > 0 do
(
append mySortedArray myFilteredNames[myFilteredNames.count]
myFilteredNames.count = (myFilteredNames.count-1)
)
fn reverseStringSort s1 s2 = (stricmp s2 s1)
qsort str_array reverseStringSort
Or the less intimidating but slower alternative,
theArray = #("2011.01.15", "2009.01.15", "2011.05.16", "2010.05.22")
sort theArray --sort forward
theArray = for i = theArray.count to 1 by -1 collect theArray[i] --collect backwards
-->#("2011.05.16", "2011.01.15", "2010.05.22", "2009.01.15")
slower but memory friendly:
for k=1 to arr.count/2 do swap arr[k] arr[arr.count-k+1]
I wanted to learn more about the code you guys posted, so I went ahead and put them all into a script and time stamped them operating on an array with 500,000 date entries. Here are the results of my tests:
"Array built and sorted in 10.8sec with 500,000 entries."
"Sort in 2.3sec."
"DenisT#1 sort in 7.8sec."
"Bobo sort in 0.9sec."
"DenisT#2 sort in 0.6sec."
Here is the code I used to arrive at the above data:
(
myArray = #()
local start = timeStamp()
for i = 1 to 500000 do
(
local myRandomYear = (random 2010 2011)
local myRandomMonth = (random 01 12)
local myRandomDay = (random 01 28)
--pad a 0 before single digit values
if myRandomMonth < 10 then (myRandomMonth = "0" + myRandomMonth as string);myRandomMonth as integer
if myRandomDay < 10 then (myRandomDay = "0" + myRandomDay as string);myRandomDay as integer
local myDateString = myRandomYear as string + "," + myRandomMonth as string + "," + myRandomDay as string
append myArray myDateString
)
sort myArray --sort forward
theFeedbackTxt = "Array built and sorted in " + (formattedPrint ((timeStamp() - start) / 1000.0) format:".1f") + "sec with 500,000 entries."
print theFeedbackTxt
/*
--time stamp method
local mySortedArray = #()
local start = timeStamp()
while myArray.count > 0 do
(
append mySortedArray myArray[myArray.count]
myArray.count = (myArray.count-1)
)
theFeedbackTxt = "Sort in " + (formattedPrint ((timeStamp() - start) / 1000.0) format:".1f") + "sec."
print theFeedbackTxt
*/
/*
--time stamp denisT's method #1
local start = timeStamp()
fn reverseStringSort s1 s2 = (stricmp s2 s1)
qsort myArray reverseStringSort
theFeedbackTxt = "DenisT#1 sort in " + (formattedPrint ((timeStamp() - start) / 1000.0) format:".1f") + "sec."
print theFeedbackTxt
*/
/*
--time stamp bobo's method #1
local start = timeStamp()
myArray = for i = myArray.count to 1 by -1 collect myArray[i] --collect backwards
theFeedbackTxt = "Bobo sort in " + (formattedPrint ((timeStamp() - start) / 1000.0) format:".1f") + "sec."
print theFeedbackTxt
*/
--/*
--time stamp denisT's method #2
local start = timeStamp()
for k=1 to myArray.count/2 do swap myArray[k] myArray[myArray.count-k+1]
theFeedbackTxt = "DenisT#2 sort in " + (formattedPrint ((timeStamp() - start) / 1000.0) format:".1f") + "sec."
print theFeedbackTxt
--*/
)
Looks like denisT's 2nd method works the fastest:
for k=1 to myArray.count/2 do swap myArray[k] myArray[myArray.count-k+1]
I’ve yet to do any memory tests to see which handles the array better, but I’ll make the assumption that denisT’s 2nd method probably wins here as well.
first of all the method that you use for comparison is not correct. The methods has to sort exactly same arrays.
here is correct method for 50,000 entities:
seed 0
defdata = for k=1 to 50000 collect
(
y = random 1967 2011
m = random 1 12
d = random 1 31
(formattedPrint y format:".4d.") + (formattedPrint m format:".2d.") + (formattedPrint d format:".2d")
)
(gc())
-- TheGrak
(
data = copy defdata #nomap
gc()
t1 = timestamp()
m1 = heapfree
sort data
local sortedData = #()
while data.count > 0 do
(
append sortedData data[data.count]
data.count = (data.count-1)
)
m2 = heapfree
format "TheGrak -> time:% memory:%
" (timestamp() - t1) (m1 - m2)
)
-- Bobo
(
data = copy defdata #nomap
gc()
t1 = timestamp()
m1 = heapfree
sort data
for i = data.count to 1 by -1 collect data[i]
m2 = heapfree
format "Bobo -> time:% memory:%
" (timestamp() - t1) (m1 - m2)
)
-- denisT #1
(
fn reverseStringSort s1 s2 = (stricmp s2 s1)
data = copy defdata #nomap
gc()
t1 = timestamp()
m1 = heapfree
qsort data reverseStringSort
m2 = heapfree
format "denisT #1 -> time:% memory:%
" (timestamp() - t1) (m1 - m2)
)
-- denisT #2
(
data = copy defdata #nomap
gc()
t1 = timestamp()
m1 = heapfree
sort data
count = data.count
for k=1 to count/2 do swap data[k] data[count-k+1]
m2 = heapfree
format "denisT #2 -> time:% memory:%
" (timestamp() - t1) (m1 - m2)
)
as you see the fastest methods is Bobo’s.
the safest (speed + memory) is denisT’s #2.
QSORT function is very slow as compared with SORT and uses a lot of memory. But usually when you need to sort by Date/Time you have to sort some structures (“File, Date” for example). In this case the SORT function doesn’t work anymore and we have to use another methods. But if we use structure we don’t need to store DATE in STRING format. We can convert DATE to INTEGER. In this case the QSORT will work faster and more friendly for memory.