Take the 2-minute tour ×
Geographic Information Systems Stack Exchange is a question and answer site for cartographers, geographers and GIS professionals. It's 100% free, no registration required.

I am working on a script that will populate 3 letters into a field. I have to use letters due to field limitations and to make sure that I have enough combinations. I'm not really sure where I am going wrong but I don't get the repeated values filtered out consistently. It seems to happen most of the time, just not all. Any one see anything wrong in my code?

import random, string, arcgisscripting, time

gp = arcgisscripting.create(9.3)
gp.OverwriteOutput = 1

# Lets set up some variables
layer = "Layer Goes Here" 
field = "Code" 
length = 3 # Declares the number of character to be created.

uniquelist = [] # Empty list to store already created characters.


##########Define the random character generator##############

def ranchar(length):
    myrg=random.SystemRandom

    characters=["a","b","c","d","e","f","g","h","i","j","k","l","m","n","o","p","q","r","s","t","u","v","w","x","y","z"]
    pw=string.join(myrg(random).sample(characters,length))
    randomval = (pw.replace(' ', '')) # Removes some spaces between the letters.


    return randomval

#############################################################

cur = gp.UpdateCursor(layer)
row = cur.Next()

while row:
    randomval = ranchar(length) # Grabs a random character.

    if randomval in uniquelist: # check to see if it already exists.
        print str(randomval) + " already exists, generating new value"
    else:
        uniquelist.append(randomval) # If the value isn't in the list, adds it.
        print uniquelist[-1] # Just for display.
        row.SetValue(field,uniquelist[-1]) # Grabs the last value from the list and writes it.
    cur.UpdateRow(row)
    row = cur.Next()

# Delete cursor and row objects to remove locks on the data
#
del cur, row

Thanks,

-Mike

share|improve this question
add comment

2 Answers 2

up vote 4 down vote accepted

From the looks of it, you're not iterating over uniquelist in the case of a collision, something like this should do the trick:

while row:
    randomval = ranchar(length)
    while randomval in uniquelist:
        randomval = ranchar(length)

    uniquelist.append(randomval)
    row.setValue(field, randomval)
    cur.UpdateRow(row)
    row = cur.Next()
share|improve this answer
    
Thanks scw! That solved it. 100% unique characters. –  Mike Long Dec 1 '10 at 22:04
add comment

This can be golfed down quite a bit to ''.join(random.sample(string.uppercase, 3)).

import random
import string
seen_values = set()

randomvalue = ''.join(random.sample(string.uppercase, 3))
for row in cursor:
    while randomvalue in seen_values:
        randomvalue = ''.join(random.sample(string.uppercase, 3))
    seen_values.add(randomvalue)
    row.setValue('randomfield', randomvalue)

One thing to consider is the fact that you have to keep track of the values you've already run into to avoid the (very unlikely) possibility of the random generator returning the same thing more than once in longer runs, and the fact that in longer runs the set could get so large you run out of memory.

Another issue here: are you assigning all values? If not, you could have the possibility that some rows already have "random" values that could be run into again, so you need to open up a cursor and populate seen_values before calculating the rest.

Another question: does it just need to be unique, or truly random? You could do something reproducible like an in-order identification:

import string
import itertools
my_iter = itertools.combinations(string.uppercase, 3)

for row in cursor:
    row.setValue('orderedfield', ''.join(my_iter.next()))

Then the rows will be unique, but identified as ABC, ABD, ABE, ... XYZ and you don't need to keep track of the values you've already run into, assuming you're calculating all values.

share|improve this answer
    
Thanks Jason. I will have to test out what you posted. –  Mike Long Dec 2 '10 at 13:58
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.