Notifications
Clear all

[Closed] sort array problem

--hey,guys! I have a problem like this:

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

--after select some of them and collect their names
spherename=for i in selection collect i.name
--sometime result like this in ascending order:
--#("Sphere09", "Sphere10", "Sphere11", "Sphere12", "Sphere13","Sphere100", "Sphere101", "Sphere102", "Sphere103", "Sphere104")

--sometime the result is not in ascending order,so I use sort on it
sort spherename
--alas! I got result like this
--#("Sphere09", "Sphere10", "Sphere100", "Sphere101", "Sphere102", "Sphere103", "Sphere104","Sphere10", "Sphere11", "Sphere12", "Sphere13")

--anybody help me get an ascending order,thanks!
35 Replies
1 Reply
(@gazybara)
Joined: 11 months ago

Posts: 0

For your examle you can try something like this


 delete objects
 speresArr = for i=1 to 120 collect (sphere radius:(random 4 10) pos:(random [-100.0,-100.0,-100.0] [100.0,100.0,100.0]))
 handleArr = sort (for i = 1 to 10 collect getHandleByAnim speresArr[random 1 120])
 sphereNames = for i in handleArr collect (getAnimByHandle i).name
 

it calls ‘natural numeric sort’. try to find a solution on the internet. there are many examples.
.net has a built-in solution. and you can use .net with mxs

1 Reply
(@gazybara)
Joined: 11 months ago

Posts: 0

This seems interesting. Can anyone translate this?

You could also name the nodes with a consistent number of digits to solve the problems sorting the array.

In Max 2011+ you can use "uniqueName" function or "nameSuffixLength" property. 
uniqueName <prefix> [numDigits:<integer>]
maxOps.nameSuffixLength

In versions previous to 2011 you could use “formattedPrint” to rename the nodes using a given number of digits. In the following example spheres are renamed to “Sphere001”, “Sphere002” and so on:

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

THANK Branko Živković,
THANK Jorge Rodríguez,
Denis Trofimov you like a teacher,give me a clue and help me solve my trouble by myself,I believe this is a good way to learning. but please remember google can’t use freely in my country.

well… let’s do the natural sort using pure MXS…
i will show just how the things work, and i will try to do it simple and clear

first of all is about the problem. try to sort the built-in way:

maxOps.nameSuffixLength = 1
 
 for k=1 to 1000 do box()
 nn = for obj in objects collect obj.name
 sort nn

you can see that higher indexed objects are going before lower.
i want to have them as 1,2,3,etc.

the step #1.
#1 to learn how to split the numerated name on two parts: base and index.
the easiest and most ‘economic’ method i found is:

fn splitNumeratedName name =
 (
 	base = trimright name "0123456789"
 	id = substring name (base.count+1) -1
 	#(base, id)
 )
 

#2 make a qsort function using a split method:

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
 	)
 )
 

#3 just sort it with qsort:

qsort nn naturalSort 

where is a problem(s) ?
it works well and fast enough for 1000 objects but let’s do it for 20000:

delete objects
for k=1 to 20000 do box()
nn = for obj in objects collect obj.name

and sort:

t1 = timestamp()
m1 = heapfree
qsort nn namuralSort
format "time:% memory:%
" (timestamp() - t1) (m1 - heapfree) 

we can probably leave with the speed (~2.5 sec on my machine) but the memory usage is too big.
this is a general problem for all mxs string methods. MXS doesn’t do in-place string operations. every time it makes a new instance of a string object. that’s way all string operations are expensive in mxs, and why you have to avoid using of them where it possible.

now is an ‘after lesson’ question:

  • how can we improve the sorting method shown above to make it faster and more memory friendly?

Do you think that mxs solution can beat .net solution in terms of sorting speed?
I mean using Regex.
edit…
Another interesting thread (C# solutions #1 and #2)

2 Replies
(@denist)
Joined: 11 months ago

Posts: 0

no. mxs solution can’t beat c++. i’m absolutely sure about it

(@denist)
Joined: 11 months ago

Posts: 0

both solutions are very far from being good
regex is too much for this task.

My try

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)
   )
   delete objects
   nn = for i = 1 to 20000 collect 
  ( 
 	node = box()
 	splitNumeratedName node.name
 )
   qsort nn naturalSort
Page 1 / 3