Función para detectar palabras en archivo txt

publicado por: Anonymous

Estaba intentando construir una función para puntuar (en este caso penalizar) oraciones dependiendo de si las palabras que contiene cada oración existen en un archivo txt. Entre asteriscos **** he escrito la parte difícil, a modo de pseudocódigo.

def marking_sentences(corpus):
    points = []
    for comment in corpus:
        if comment ****exist in file.txt****:
            points.append(-20)
        else:
            points.append(0)
    return points

Pongamos que corpus en este caso toma un objeto del siguiente tipo:

Frases = ['Too many people', 'We can do it']

Pongamos que el archivo *.txt contiene dos palabras: “people”, “fire”.

Me gustaría saber si voy bien encaminado o si es más complejo de lo que pienso. Obtener una lista en la que cada valor correspondiera a la asignación de puntos para cada frase sería el objetivo. En el caso del ejemplo la salida sería [-20, 0]

He intentado esto:

with open('data.txt', 'r') as handle:
    word_list = []
    for line in handle:
        word_list.append(line)
print (word_list)
#Asignando puntos:
def marking_swear(corpus):
    points = []
    for comment in corpus:
        if comment in word_list:
            points.append(-20)
        else:
            points.append(0)
    return points

solución

Podrías seguir esa idea pero ten en cuenta que si lo que quieres es ver si una palabra está o no en un comentario, primero debes dividir cada comentario en palabras. Podrías comprobar si una palabra es una subcadena de un comentario con simplemente hacer if palabra in comentario, pero hacer esto significa que if "casa" in comentario retornaría True tanto para "Tengo una casa" como para "Eso es escasamente probable"

Si tus comentarios solo contienen palabras y espacios entre ellas bastaría con usar str.split(). Esto generalmente no es así, sino que te puedes encontrar la palabra acompañada de otros signos gramaticales: “fire?”, “fire!”, “fire.”, “fire, “, etc.

En estos casos lo que se suele intentar es normalizar la cadena, incluido la presencia de mayúsculas. Es un tema más complejo de lo que parece a simple vista y hay diferentes formas de abordarlo dependiendo del caso particular.

Una opción por su flexibilidad es usar expresiones regulares. Por ejemplo, algo simple para tu caso sería:

import re
Frases = ['Too many people',
          'We can do it', 
          'I am on Fire', 
          'The campfire is the new dinner party', 
          'Ready, aim, FIRE!!!']

with open("penalize.txt") as f:
    list_patterns = [word.strip() for word in f]

pattern = re.compile(r"|".join(r"b{}b".format(re.escape(p)) for p in list_patterns), 
                     flags=re.IGNORECASE)
res = [-20 if re.search(pattern, frase) else 0 for frase in Frases]
print(res)

Partimos de un penalize.txt como el siguiente:

people
fire

Y la salida es:

[-20, 0, -20, 0, -20]

En este ejemplo si cualquiera de las palabras contenidas en el txt está en el comentario la puntuación será -20. No se tiene en cuenta que aparezca más de una vez o que aparezcan varias palabras en el mismo comentario, aunque penalizar en función de lo anterior sería relativamente simple también.

La clave aquí esta en la creación de una expresión regular:

r"|".join(r"b{}b".format(re.escape(p)) for p in list_patterns

Con lo que se pretende construir patrones de la forma:

r"bfireb|bpeopleb"

Se usa un or para capturar cualquier subcadena que cumpla con el patrón bpalabrab donde b es conocida como “word boundary”, de la documentación oficial de Python:

b
Coincide con la cadena vacía, pero solo al principio o al final de una palabra. Una palabra se define como una secuencia de caracteres alfanuméricos o subrayado (_), por lo que el final de una palabra se indica con espacios en blanco o un carácter no alfanumérico y sin subrayado. Tenga en cuenta que formalmente, b se define como el límite entre un carácter w y un W (o viceversa), o entre w y el principio / final de la cadena, por lo que el conjunto preciso de caracteres considerados alfanuméricos depende en los valores de los indicadores UNICODE y LOCALE. Por ejemplo, r ‘ bfoo b’ coincide con ‘foo’, ‘foo.’, ‘(Foo)’, ‘bar foo baz’ pero no ‘foobar’ o ‘foo3’. Dentro de un rango de caracteres, b representa el carácter de retroceso, para la compatibilidad con los literales de cadenas de Python.

Las mayúsculas son ignoradas, es decir “Fire”, “fire”, “FIRE”, “FiRe” son consideradas la misma palabra.

Lo anterior no es perfecto ni tiene por que ser la opción más eficiente en tu caso, como se ha indicado es un problema complejo ya que estamos tratando con lenguaje natural y con personas que no siempre tienen porqué seguir las reglas gramaticales con precisión :), hay que tener en cuenta muchos aspectos.

Respondido por: Anonymous

Leave a Reply

Your email address will not be published. Required fields are marked *