Contando y marcando frases de dos y tres palabras -- python campo con performance campo con beginner campo con python-2.x campo con hash-map camp codereview Relacionados El problema

Counting and scoring two- and three-word phrases


1
vote

problema

Español

Estoy escribiendo una función para tomar una lista de palabras y puntuar 2 y 3 frases de Word basadas en ocurrencia mientras se eliminan las ocurrencias de la frase con una puntuación de menos de 3.

Como alguien un poco nuevo en Python, me pregunto si hay una mejor manera de escribir esto para hacer lo mismo (el código funciona)

El diccionario resultante se ve algo así ...

  (5+16(8-4))/162  

  (5+16(8-4))/163  
Original en ingles

I am writing a function to take a list of words and score 2 and 3 word phrases based on occurrence while removing any phrase occurrences with a score of less than 3.

As someone kinda new to python, i'm wondering if there is a better way to write this to do the same thing (the code works)

The resulting dictionary looks something like this...

{ ( "lorem ipsum", 4 ), ("quick brown fox", 3), (...) } 

## -words- is a list of words ## -phrases- is the resulting dictionary with the phrase as a key and score as a value  words = ("lorem","ipsum","lorem","ipsum","quick","brown","fox") phrases = dict()  for i, w in enumerate(words):      w = re.sub('[^0-9a-zA-Z]+', '', w).lower()      try:         w1 = " " + re.sub('[^0-9a-zA-Z]+', '', words[ i + 1 ]).lower()     except:         w1 = ""      try:         w2 = " " + re.sub('[^0-9a-zA-Z]+', '', words[ i + 2 ]).lower()     except:         w2 = ""      if w!="" and not w.isdigit() and len(w)>1:          p = w + w1         p2 = w + w1 + w2          try:             phrases[p] = phrases[p] + 1         except:             phrases[p] = 1          try:             phrases[p2] = phrases[p2] + 1         except:             phrases[p2] = 1  phrases = { k:v for k, v in phrases.items() if v > 2 }  rc = sorted(phrases.items(), key=lambda x: x[1], reverse = True) 
              
 
 

Lista de respuestas

4
 
vote
vote
La mejor respuesta
 

Así que redito tu bucle principal para hacerlo más Pythonic. El bucle interno completado está a continuación. Pero primero hemos discutido algunos de los cambios.

Si el espacio permite, cree una estructura de datos intermedios para facilitar el procesamiento posterior

Por lo tanto, este tipo de código se recupera la lista de palabras en una sola lista que se procesa más fácilmente en el bucle principal.

  words_x = [re.sub('[^0-9a-zA-Z]+', '', w) for w in words] + ['', '']   

lo hace:

  1. Agregue un poco de acolchado al final para el procesamiento de la lista final. No estaba seguro de que esto fuera realmente preciso con el algoritmo descrito, pero sí emula el comportamiento existente.

  2. realiza la sustitución regex solo una vez.

Si el espacio no permite construir otra estructura de datos, el módulo 99887766555443311 tiene varias herramientas que pueden permitir la iteración eficiente sobre las estructuras de datos, y a menudo vale la pena investigar.

zip () permite procesar más de una lista a una hora

Así que reestructuré el bucle para parecer:

  for w, w1, w2 in zip(words_x, words_x[1:], words_x[2:]):   

Esto itera a través de la necesidad de un índice de lista y obtiene tres palabras adyacentes cada iteración.

zip() trabaja por el iterativo a través de cada uno de sus argumentos, y presentando el primer elemento de cada lista la primera vez que se llama, y ​​luego el segundo elemento de cada lista, y luego ... y llamándolo con la misma lista, pero comenzando en el 1º, 2º y 3º elementos respectivamente, podemos obtener tres elementos adyacentes cada iteración.

use collections.Counter

Entonces Python tiene una estructura de datos ingeniosa que actúa mucho como un diccionario, pero se usa para contar. Es extrañamente lo suficientemente llamado Counter .

contador permite reemplazar:

  try:     phrases[p] = phrases[p] + 1 except:     phrases[p] = 1   

con:

  phrases[w] += 1   

Código:

  from collections import Counter  words = ("lorem", "ipsum", "lorem", "ipsum", "quick", "brown", "fox") words_x = [re.sub('[^0-9a-zA-Z]+', '', w) for w in words] + ['', '']  phrases = Counter() for w, w1, w2 in zip(words_x, words_x[1:], words_x[2:]):      if len(w) > 1 and not w.isdigit():         if w1:             w += ' ' + w1         phrases[w] += 1         if w2:             w += ' ' + w2         phrases[w] += 1   

BURS?:

el código sale del final de la lista:

El código actual sale del final de la lista. El efecto de esto puede verse por el hecho de que la palabra "Fox" de la palabra soltera termina en la lista de frases. El código actual busca cualquier frase que exista más de una vez, por lo que esta palabra finalmente se cae, pero ...

Al final de la lista, la última frase de Word Double contada como una frase de tres palabras

En el código actual, brown fox se cuenta dos veces.

El código a continuación fija ambos problemas de condición de terminales.

Código revisado:

  itertools0  
 

So I redid your main loop to make it more pythonic. The completed inner loop is below. But first let us discuss some of the changes.

If space allows, build intermediate data structure to ease later processing

So this bit of code recasts the word list into a single list that is more readily processed in the main loop.

words_x = [re.sub('[^0-9a-zA-Z]+', '', w) for w in words] + ['', ''] 

It does:

  1. Add some padding at the end for end of list processing. I wasn't sure that this was actually accurate to the described algorithm, but it does emulate the existing behavior.

  2. Perform the regex substitution only once.

If space does not allow building another data structure, the itertools module has various tools that may allow efficient iterating over a data structures, and is often worth investigating.

zip() allows processing more than one list at a time

So I restructured the loop to look like:

for w, w1, w2 in zip(words_x, words_x[1:], words_x[2:]): 

This iterates through without the need for a list index and gets three adjacent words each iteration.

zip() works by iterating through each of its arguments, and presenting the first element of each list the first time it is called, and then the second element of each list, and then... And by calling it with the same list but starting at the 1st, 2nd and 3rd elements respectively, we can get three adjacent elements each iteration.

Use collections.Counter

So python has a nifty data structure that acts a lot like a dictionary but is used for counting. It is oddly enough called Counter.

Counter allows replacing:

try:     phrases[p] = phrases[p] + 1 except:     phrases[p] = 1 

with:

phrases[w] += 1 

Code:

from collections import Counter  words = ("lorem", "ipsum", "lorem", "ipsum", "quick", "brown", "fox") words_x = [re.sub('[^0-9a-zA-Z]+', '', w) for w in words] + ['', '']  phrases = Counter() for w, w1, w2 in zip(words_x, words_x[1:], words_x[2:]):      if len(w) > 1 and not w.isdigit():         if w1:             w += ' ' + w1         phrases[w] += 1         if w2:             w += ' ' + w2         phrases[w] += 1 

Bugs?:

Code walks off the end of the list:

The current code walks off the end of the list. The effect of this can be seen by the fact that the single word 'fox' ends up in the phrases list. The current code looks for any phrase that exists more than once, so this word is eventually dropped, but...

At the end of the list the last two word phrase double counted as a three word phrase

In the current code, brown fox is counted twice.

The code below fixes both terminal condition problems.

Revised Code:

from collections import Counter  words = ("lorem", "ipsum", "lorem", "ipsum", "quick", "brown", "fox") REMOVE_EXTRA = re.compile(r'[^0-9a-zA-Z]+') words_x = [REMOVE_EXTRA.sub('', w) for w in words] + ['']  phrases = Counter() for w, w1, w2 in zip(words_x, words_x[1:], words_x[2:]):      if len(w) > 1 and not w.isdigit():         if w1:             w += ' ' + w1         phrases[w] += 1         if w2:             # only count as three word phrase if w2 is not blank             phrases[w + ' ' + w2] += 1 
 
 

Relacionados problema

3  Compara los dictos y récord de cambios  ( Compare dicts and record changes ) 
Mi objetivo es actualizar continuamente un objeto y registrar cualquier cambio y las veces que se hicieron. La entrada debe ser JSON, pero el formato de salid...

6  Hosth de descarga en columnas  ( Dump hash in columns ) 
Intenté responder a la pregunta "¿Cómo imprimir un hash en Perl, de modo que se imprimen 3 pares de valor clave en cada línea? " como este . Como obtuve u...

5  Finanzas familiares - seguimiento e informes  ( Family finances tracking and reporting ) 
Estoy buscando una forma limpia de acumular montos dentro de un conjunto de datos de entrada. En este ejemplo, hay 18 filas de datos, y la salida es de 3 fila...

7  Holding registros utilizando diccionario  ( Holding records using dictionary ) 
¿Puedes por favor ayudarme con el siguiente script? En este momento, el script está tomando hasta 20 minutos para ejecutar, dependiendo de la cantidad de da...

2  Tabla hash implementada por JavaScript  ( Hash table implemented by javascript ) 
Recientemente intenté implementar una tabla simple usando JavaScript. ¿Alguien podría ayudarme a revisar mi implementación? AssetClass6 En mi implement...

0  Acelerar el código basado en el mapa con vectores como valores  ( Speed up code based on map with vectors as values ) 
Siguiendo es la pieza de código que representa el cuello de botella de mi aplicación: #include <iostream> #include <chrono> #include <unordered_map> #inclu...

5  Producto cartesiano de Python en un dictnario limitado  ( Python cartesian product in a constrained dictonary ) 
Quiero calcular el producto cartesiano de n Copias de una lista pequeña, 9988777665544331 . Quiero usar estas tites de productos cartesianos como llaves en...

4  Un programa para mostrar, actualizar y guardar un diccionario como .csv  ( A program to display update and save a dictionary as csv ) 
Ahora estoy buscando comentarios en v2.0 de este programa en su lugar. Me gustaría algunos comentarios sobre mi código. ¿Qué malos hábitos tengo? ¿Qué c...

4  Encuentra y reemplaza la optimización del método  ( String find and replace method optimization ) 
Estoy tratando de encontrar una cadena de encabezado específica de diferentes mapas ( 9988777665544330 , LEDES98BIheaders1 y LEDES98BI_V2headers ) En un e...

0  Base de datos de estudiantes  ( Database of students ) 
Al principio, tuve 9988777665544332 para contener std::list<Student> students , pero como hay más de 2000 estudiantes, la búsqueda de estudiantes no debe h...




© 2022 respuesta.top Reservados todos los derechos. Centro de preguntas y respuestas reservados todos los derechos