4 votos

Ayuda del generador de personajes únicos

Estoy trabajando en un script que rellenará 3 letras en un campo. Tengo que usar letras debido a las limitaciones del campo y para asegurarme de que tengo suficientes combinaciones. No estoy muy seguro de dónde me estoy equivocando, pero no consigo filtrar los valores repetidos de forma consistente. Parece que ocurre la mayoría de las veces, pero no todas. ¿Alguien ve algo malo en mi código?

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

Gracias,

-Mike

4voto

Paul Puntos 555

Esto se puede reducir bastante a ''.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)

Una cosa a tener en cuenta es el hecho de que tienes que llevar la cuenta de los valores con los que ya has corrido para evitar la posibilidad (muy improbable) de que el generador aleatorio devuelva la misma cosa más de una vez en las ejecuciones más largas, y el hecho de que en las ejecuciones más largas el conjunto podría llegar a ser tan grande que te quedas sin memoria.

Otra cuestión: ¿está asignando todos los valores? Si no es así, podrías tener la posibilidad de que algunas filas ya tengan valores "aleatorios" con los que podrías toparte de nuevo, por lo que necesitas abrir un cursor y rellenar seen_values antes de calcular el resto.

Otra pregunta: ¿es necesario que sea único o realmente aleatorio? Se podría hacer algo reproducible como una identificación en orden:

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

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

Entonces las filas serán únicas, pero identificadas como ABC, ABD, ABE, ... XYZ y no necesita llevar la cuenta de los valores con los que ya se ha topado, suponiendo que está calculando todos los valores.

3voto

Robert Höglund Puntos 5572

Por lo que parece, no estás iterando sobre uniquelist en caso de colisión, algo como esto debería servir:

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

i-Ciencias.com

I-Ciencias es una comunidad de estudiantes y amantes de la ciencia en la que puedes resolver tus problemas y dudas.
Puedes consultar las preguntas de otros usuarios, hacer tus propias preguntas o resolver las de los demás.

Powered by:

X