2009-03-31 10 views
5

Di que tengo una cadena de palabras: 'a b c d e f'. Quiero generar una lista de términos de varias palabras de esta cadena.¿Cómo puedo generar términos de varias palabras recursivamente?

El orden de las palabras importa. El término 'f e d' no se debe generar a partir del ejemplo anterior.

Editar: Además, no se deben omitir las palabras. 'a c' o 'b d f' no se debe generar.

lo que tengo en este momento:

doc = 'a b c d e f' 
terms= [] 
one_before = None 
two_before = None 
for word in doc.split(None): 
    terms.append(word) 
    if one_before: 
     terms.append(' '.join([one_before, word])) 
    if two_before: 
     terms.append(' '.join([two_before, one_before, word])) 
    two_before = one_before 
    one_before = word 

for term in terms: 
    print term 

Lienzo:

a 
b 
a b 
c 
b c 
a b c 
d 
c d 
b c d 
e 
d e 
c d e 
f 
e f 
d e f 

¿Cómo puedo hacer esto una función recursiva para que pueda pasar un número variable máximo de las palabras por término?

Aplicación:

voy a utilizar este para generar términos de varias palabras de texto legible en los documentos HTML. El objetivo general es un análisis semántico latente de un gran corpus (alrededor de dos millones de documentos). Esta es la razón por la cual el orden de las palabras importa (procesamiento del lenguaje natural y otras cosas).

+0

Para simplificar he sustituido letras sueltas por palabras. – tgray

+0

¿te refieres a "cantidad máxima variable de términos por palabras"? porque no tiene sentido para mí en su forma actual. – SilentGhost

+0

Creo que la verdadera pregunta aquí es, ¿necesita ser recurrente para hacer el trabajo? ¿Hay algún requisito para la recursión aquí? –

Respuesta

11

Esto no es recursivo, pero creo que hace lo que usted quiere.

doc = 'a b c d e f' 
words = doc.split(None) 
max = 3   


for index in xrange(len(words)):  
    for n in xrange(max): 
     if index + n < len(words):   
      print ' '.join(words[index:index+n+1]) 

Y he aquí una solución recursiva:

def find_terms(words, max_words_per_term):  
    if len(words) == 0: return [] 
    return [" ".join(words[:i+1]) for i in xrange(min(len(words), max_words_per_term))] + find_terms(words[1:], max_words_per_term) 


doc = 'a b c d e f' 
words = doc.split(None) 
for term in find_terms(words, 3): 
    print term 

Ésta es la función recursiva de nuevo, con algunas variables que explican y comentarios.

def find_terms(words, max_words_per_term): 

    # If there are no words, you've reached the end. Stop.  
    if len(words) == 0: 
     return []  

    # What's the max term length you could generate from the remaining 
    # words? It's the lesser of max_words_per_term and how many words 
    # you have left.               
    max_term_len = min(len(words), max_words_per_term)  

    # Find all the terms that start with the first word. 
    initial_terms = [" ".join(words[:i+1]) for i in xrange(max_term_len)] 

    # Here's the recursion. Find all of the terms in the list 
    # of all but the first word. 
    other_terms = find_terms(words[1:], max_words_per_term) 

    # Now put the two lists of terms together to get the answer. 
    return initial_terms + other_terms 
+0

Parece que tendré que usar la primera solución que me proporcionó. Python no permitirá que una función se repita más de 999 veces. Mi documento de prueba tenía aproximadamente 1750 palabras y es un poco pequeño. – tgray

+0

Eso tiene sentido. La solución recursiva fue divertida de resolver, pero no realmente práctica. –

+0

Si realmente desea tener recursión profunda, puede aumentar el límite de recursión con sys.setrecursionlimit. Pero la solución iterativa es probablemente mejor aquí de todos modos. – Kiv

3

Sugiero que debe hacer de su función un generador y luego generar el número requerido de términos. Debería cambiar print a yield (y hacer que funcione todo el bloque, obviamente).

También puede consultar el módulo itertools, es bastante útil para el tipo de trabajo que realiza.

3

¿Por qué haces esto? En su lugar, solo puede usar un ciclo for y itertools.combinations().

+0

Buena sugerencia, pero necesito que se guarde la orden. Ejemplo: 'a b c' crea ['a', 'b', 'a b', 'c', 'b c', 'a b c'], pero no 'b a' o 'c b a'. – tgray

+0

Mantiene el orden. –

+0

Disculpe la confusión, tampoco debería omitir palabras. El documento "El rápido zorro marrón saltó sobre la valla" no debería tener "valla marrón" como término. ¿Hay alguna manera de usar itertools para hacer esto? – tgray

1

Lo que está buscando es algoritmo N-gram. Eso te dará [a, ab, b, bc, c, cd, ...].

Cuestiones relacionadas