# Scripting – Shuffling a collection to randomly select by percentage Via a tech-artists.org tweet, I came across some MAXScript for randomly selecting a specified percentage of mesh elements (for example, give me a random selection that includes 35% of all vertices).

I converted it to Python in Softimage. Note that I don’t really shuffle a collection: you can’t set items in a collection, so there’s no way to swap items. Instead, I put the collection in a list and shuffle the list.

Shuffling actually makes this harder than it has to be. Check out Alan’s nice script for a better way to do this.

```si = Application
log = si.LogMessage
sisel = si.Selection

import random

#
# Return a list that includes a randomly selected
# percentage of the items in a collection
#
def get_random_percentage( collection, percentage ):
v = [x for x in collection]

# random shuffle
for i in range( len(v) ):
j = random.randint( i, len(v)-1 )
v[i], v[j] = v[j], v[i]

# select by percentage
step = 100/percentage
w = []
for i in xrange( 0, len(v), step ):
w.append( v[i] )

#	print len(w)
#	print (percentage/100.0) * len(v)

return w

Application.SelectObj("torus", "", True)
# Select a random 50% of the vertices
x = get_random_percentage( sisel(0).ActivePrimitive.Geometry.Vertices, 50 )
si.SelectObj(x)

print sisel(0).SubComponent.ComponentCollection.Count

# Suppose you had 2000 cubes.
# Select a random 25% of those 2000...
Application.SelectObj("cube*", "", True)
x = get_random_percentage( sisel, 25 )
si.SelectObj(x)
```

I learned a couple of things about MAXScript:

• MAXScript arrays are 1-based
• In the MaxScript docs, there aren’t any function/method reference pages. You have to go to a “value” page (eg Number Values) and there you’ll find all the methods. That’s fine once you know, but it was confusing at first when I didn’t see anything in the TOC for Functions or Methods.

## 4 thoughts on “Scripting – Shuffling a collection to randomly select by percentage”

1. darkvertex on said:

With all due respect, you are going a very convoluted route with all this. You can do:

def get_random_percentage(iterable, percentage):
amount = int( float(len(iterable)) * (percentage/100.0) )
return random.sample(iterable, amount)

Check out my neat version of your example here:

 from win32com.client import constants as c import random xsi = Application XSIDialog = XSIFactory.CreateObject("XSIDial.XSIDialog") def get_random_percentage(iterable, percentage): amount = int( float(len(iterable)) * (percentage/100.0) ) return random.sample(iterable, amount) def selectRandomComponents(coll, percentage, cmpType = 'ask'): allComponents = { 'edges':[x for obj in coll for x in obj.ActivePrimitive.Geometry.Edges], 'points':[x for obj in coll for x in obj.ActivePrimitive.Geometry.Points], 'faces':[x for obj in coll for x in obj.ActivePrimitive.Geometry.Facets] } cmpTypes = allComponents.keys() if cmpType == 'ask': cmpType = cmpTypes[ XSIDialog.ComboEx('Component type?',cmpTypes,2) ] sample = get_random_percentage(allComponents[cmpType], percentage) xsi.SelectObj(sample) def selectRandomObjects(coll, percentage): sample = get_random_percentage(coll, percentage) xsi.SelectObj(sample) def main(): selectComponents = ( XSIUIToolkit.Msgbox( "Select components?\n\nYES = components\nNO = objects", c.siMsgYesNo+c.siMsgQuestion, "Random Selector" ) == c.siMsgYes ) percentage = float(xsi.XSIInputBox( "What percentage to select?", "Selection percentage?", 50 # default % )) if selectComponents: selectRandomComponents(xsi.Selection, percentage) else: selectRandomObjects(xsi.Selection, percentage) main()

• Yes, now that I look at it, my literal conversion of that Maxscript isn’t pretty. I remember I was more focused on figuring out what that Maxscript actually did.

No offense, but “with all due respect” always makes me think something like this 😉 • darkvertex on said:

haha, well I didn’t really mean it that way. 😉 keep up the great blog! I read it every week.