Esa es una forma muy extraña de organizar las cosas. Si almacenó en un diccionario, esto es fácil:
# This example should work in any version of Python.
# urls_d will contain URL keys, with counts as values, like: {'http://www.google.fr/' : 1 }
urls_d = {}
for url in list_of_urls:
if not url in urls_d:
urls_d[url] = 1
else:
urls_d[url] += 1
Este código para actualizar un diccionario de conteos es un "patrón" común en Python. Es tan común que existe una estructura de datos especial defaultdict
, creada solo para hacer esto aún más fácil:
from collections import defaultdict # available in Python 2.5 and newer
urls_d = defaultdict(int)
for url in list_of_urls:
urls_d[url] += 1
Si accede al defaultdict
mediante una clave, y la clave aún no está en el defaultdict
, la clave se agrega automáticamente con un valor predeterminado. El defaultdict
toma el invocable que le pasó y lo llama para obtener el valor predeterminado. En este caso, pasamos en clase int
; cuando Python llama int()
, devuelve un valor cero. Entonces, la primera vez que hace referencia a una URL, su recuento se inicializa en cero y luego agrega uno al recuento.
Pero un diccionario lleno de cuentas también es un patrón común, por lo que Python proporciona una clase lista para usar: containers.Counter
simplemente crea una Counter
instancia llamando a la clase, pasando cualquier iterable; construye un diccionario donde las claves son valores del iterable, y los valores son recuentos de cuántas veces apareció la clave en el iterable. El ejemplo anterior se convierte entonces en:
from collections import Counter # available in Python 2.7 and newer
urls_d = Counter(list_of_urls)
Si realmente necesita hacerlo de la manera que mostró, la forma más fácil y rápida sería usar cualquiera de estos tres ejemplos y luego construir el que necesita.
from collections import defaultdict # available in Python 2.5 and newer
urls_d = defaultdict(int)
for url in list_of_urls:
urls_d[url] += 1
urls = [{"url": key, "nbr": value} for key, value in urls_d.items()]
Si está utilizando Python 2.7 o más reciente, puede hacerlo en una sola línea:
from collections import Counter
urls = [{"url": key, "nbr": value} for key, value in Counter(list_of_urls).items()]
Usar el predeterminado funciona, pero también lo hace:
usando
.get
, puede obtener una devolución predeterminada si no existe. Por defecto es Ninguno, pero en el caso de que te envié, sería 0.fuente
Utilice defaultdict :
fuente
Esto siempre funciona bien para mí:
fuente
¿Para hacerlo exactamente a tu manera? Podrías usar la estructura for ... else
Pero es bastante poco elegante. ¿Realmente tienes que almacenar las URL visitadas como una LISTA? Si lo ordena como un dictado, indexado por url string, por ejemplo, sería mucho más limpio:
Algunas cosas a tener en cuenta en ese segundo ejemplo:
urls
elimina la necesidad de revisar toda laurls
lista al probar una solaurl
. Este enfoque será más rápido.dict( )
llaves en lugar de llaves hace que su código sea más cortolist_of_urls
,urls
yurl
como nombres de variable hacen que el código sea bastante difícil de analizar. Es mejor encontrar algo más claro, comourls_to_visit
,urls_already_visited
ycurrent_url
. Lo sé, es más largo. Pero está más claro.Y, por supuesto, supongo que
dict(url='http://www.google.fr', nbr=1)
es una simplificación de su propia estructura de datos, porque de lo contrario,urls
podría ser simplemente:Lo que puede volverse muy elegante con la postura defaultdict :
fuente
Excepto por la primera vez, cada vez que se ve una palabra, la prueba de la instrucción if falla. Si está contando una gran cantidad de palabras, es probable que muchas ocurran varias veces. En una situación en la que la inicialización de un valor solo ocurrirá una vez y el aumento de ese valor ocurrirá muchas veces, es más barato usar una declaración try:
puede leer más sobre esto: https://wiki.python.org/moin/PythonSpeed/PerformanceTips
fuente