# 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:

This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.

 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.