Notifications
Clear all

[Closed] sort array problem

time:0.031s memory:17700L

clearListener()

speresArr = for i=1 to 200 collect (sphere radius:(random 4 10) pos:(random [-100.0,-100.0,-100.0] [100.0,100.0,100.0]))	 

tstart = timestamp()
mstart = heapfree
	 
 handleArr = sort (for i = 1 to 200 collect getHandleByAnim speresArr[i])
 sphereNames = for i in handleArr collect (getAnimByHandle i).name
	 
format "time:% memory:%
" (((timestamp()-tstart)/1000.0) as string + "s") (mstart - heapfree) 	 

--print sphereNames

time:0.172s memory:135060L

this method hard to perse,just for comparison.

clearListener()

tstart = timestamp()
mstart = heapfree

for i = 1 to 200 do
    (
    	sphere	radius:(random 4 10) \
    			pos:(random [-100,-100,-100] [100,100,100]) \
    			name:("Sphere" + (formattedprint i format:"03i"))
    )

format "time:% memory:%
" (((timestamp()-tstart)/1000.0) as string + "s") (mstart - heapfree) 	 

--sphereNames=for i in objects collect i.name
--print sphereNames

1)time:0.031s memory:44740L
2)time:0.016s memory:1148L

clearListener()

fn splitNumeratedName name =
    (
  	      string = trimright name "0123456789"
  	      number = substring name (string.count+1) -1
  	      #(string, number)
    )
fn naturalSort arr1 arr2 =
(
	 if (act = stricmp arr1[1] arr2[1]) != 0 then act else (arr1[2] as integer - arr2[2] as integer)
)


--test
 for i=1 to 200 do (sphere radius:(random 4 10) pos:(random [-100.0,-100.0,-100.0] [100.0,100.0,100.0]))

--1)	 
sphereNames=for i in objects collect (splitNumeratedName i.name ) 	
	 
tstart = timestamp()
mstart = heapfree	

--2)	 
--sphereNames=for i in objects collect (splitNumeratedName i.name ) 
   
qsort sphereNames naturalSort
 
format "time:% memory:%
" (((timestamp()-tstart)/1000.0) as string + "s") (mstart - heapfree) 

--print sphereNames
1 Reply
(@gazybara)
Joined: 11 months ago

Posts: 0

This is not my method but slightly modifierd verion of original Denis code.
My first methid will only help you only when you want to sort newly created nodes.

1.Mscript):time:0.031s memory:334060L

clearListener()

fn naturalSort name1 name2 = 
 (
 	base1 = trimright name1 "0123456789"
 	base2 = trimright name2 "0123456789"
 	
 	if (act = stricmp base1 base2) != 0 then (act) else
 	(
 		id1 = substring name1 (base1.count+1) -1 
 		id2 = substring name2 (base2.count+1) -1 
 		id1 as integer - id2 as integer
 	)
 )

 
--test
for i=1 to 200 do (sphere radius:(random 4 10) pos:(random [-100.0,-100.0,-100.0] [100.0,100.0,100.0]))
sphereNames=for i in objects collect i.name
 
tstart = timestamp()
mstart = heapfree

qsort sphereNames naturalSort

format "time:% memory:%
" (((timestamp()-tstart)/1000.0) as string + "s") (mstart - heapfree) 

--print sphereNames

2.net): time:0.016s memory:1968L

clearListener()

fn makeIComparersAssembly = 
(
	source = ""
	source += "using System;
"
	source += "using System.Runtime.InteropServices;
"
	source += "using System.Collections;
"
	source += "namespace IComparers
"
	source += "{
"
	source += "	public sealed class StringLogicalComparer: IComparer
"
	source += "	{
"
	source += "		[DllImport(\"shlwapi.dll\", CharSet = CharSet.Unicode, ExactSpelling = true)]
"
	source += "		static extern int StrCmpLogicalW(String x, String y);
"
	source += "		public int Compare(object x, object y)
"
	source += "		{
"
	source += "			return StrCmpLogicalW((String)x, (String)y);
"
	source += "		}
"
	source += "	}
"
	source += "}
"

	csharpProvider = dotnetobject "Microsoft.CSharp.CSharpCodeProvider"
	compilerParams = dotnetobject "System.CodeDom.Compiler.CompilerParameters"

	compilerParams.GenerateInMemory = on
	compilerResults = csharpProvider.CompileAssemblyFromSource compilerParams #(source)
	compilerResults.CompiledAssembly
)
global StringLogicalComparer = (makeIComparersAssembly()).createInstance "IComparers.StringLogicalComparer"


--test	
for i=1 to 200 do (sphere radius:(random 4 10) pos:(random [-100.0,-100.0,-100.0] [100.0,100.0,100.0]))
sphereNames=for i in objects collect i.name	


tstart = timestamp()
mstart = heapfree

	a = dotnet.valuetodotnetobject sphereNames (dotnetclass "System.String[]")	
	a.Sort a StringLogicalComparer

format "time:% memory:%
" (((timestamp()-tstart)/1000.0) as string + "s") (mstart - heapfree) 

--print (a.Clone())

DenisT is awesome!

If this information is intended to be a reference for other developers (as you stated), you might want to review it as it is partially inaccurate.

#1. I’ve not provided a sorting algorithm.
#2. You are comparing sorting algorithms times with nodes creation times.
#3. If you have #(“A01”, “A100”) it would be better to have either #(“A001”, “A100”) or #(“A1”, “A100”).

If you decide to use #(“A001”, “A100”) then you could use some of the code mentioned earlier.
If you decide to use #(“A1”, “A100”) then Denis solution is probably the best you can do (although for this very specific task there might be some faster way of doing it ;))

calm down… i’m absolutely agree with you that this particular problem was happened because of not well organized node name increment. but it’s a common problem. see the windows. it sorts files alphabetical way instead of natural.

(but i’m absolutely agreed with you – if you expect to have 3N nodes of the same kind, you have to preserve three digits for their index)

Yep. Also 99.9% of WIN softwares have same issue.

Page 3 / 3