[Python-es] Iterar 2 veces sobre 1 lista y comparar sus objetos lo mas rapido
lopz
lowlifebob en gmail.com
Lun Mayo 9 00:17:06 CEST 2011
Hola, estoy haciendo unas pequeñas pruebas en pygame
tengo un diccionario de palabras con tus tags, cada palabra será una
bola y si alguna de las palabras tiene igual tag que otra
entonces se unirán con una línea, y así hasta iterar sobre toda el diccionario
actualmente tengo esto y funciona bien
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import pygame
import random
class Neurons():#pygame.sprite.Sprite):
def __init__(self, x, y, color, key, tags):
self.x = x
self.y = y
self.color = color
self.key = key
self.tags = tags
def draw(self, surf):
pygame.draw.circle(surf, self.color, [self.x, self.y], 10)
def pos(self):
return (self.x, self.y)
def line(surf, start, end):
pygame.draw.line(surf, read, start, end, 1)
words = {'uno': '1 2 3',
'dos': '3 4 5',
'tres': '5 6 7',
'cuatro': '2 5 8',
'cinco': '5 3 7',
'seis': '7 6 3'}
pygame.init()
black = [0, 0, 0]
white = [255, 255, 255]
read = [255, 0, 0]
# Set the height and width of the screen
size = [400, 400]
screen = pygame.display.set_mode(size)
pygame.display.set_caption("Net")
neurons = []
for word in words:
x = random.randrange(100, 400)
y = random.randrange(100, 400)
neuron = Neurons(x, y, white, word, words[word])
neurons.append(neuron)
clock = pygame.time.Clock()
def compare(tags1, tags2):
for i in tags1.split(' '):
for j in tags2.split(' '):
if (i == j):
return True
return False
neurons2 = neurons[:]
done = False
while not done:
for event in pygame.event.get(): # User did something
if event.type == pygame.QUIT:
done = True
screen.fill(black)
for i in range(len(neurons)):
neurons[i].draw(screen)
#neuron = neurons.pop()
#neuron = neurons[i]
#neurons.remove(neurons[i])
for j in range(len(neurons)):
if (i != j):
if compare(neurons[i].tags, neurons[j].tags):
#print neurons[i].tags, neurons[j].tags
#print neuron.tags
line(screen, neurons[i].pos(), neurons[j].pos())
pygame.display.flip()
clock.tick(20)
pygame.quit()
Resulta que siempre hacía dos 2 anidados e iba comparando uno con
todos, pero ahora que me doy cuenta estoy gastando recursos
por que si una palabra y sus tags, por ej
bar: 1, 2, 3
y otra palabra
foo: 4, 2, 5
Resulta que tienen el tag 2 en común, y cuando se itera primero bar y
luego foo entonces se traza una línea entre palabras, pero cuando la
iteración
le toque a foo en el primer for y en el segundo a bar, tendrán la
mismo tag en común, entonces:
Se trazarían 2 líneas, una desde bar -> foo y otra de foo -> bar pero
como tienen los mismos puntos parece ser que es una sola línea.
Entonces he decidio cojer un objeto y eliminarlo de la lista, con pop
e iterar de nuevo pero en el segundo for ya no habría ese objeto
entonces
me ahorraría ese if ( i != j) y además menos una iteración, la próxima
menos 2 y así hasta la mitad, de funcionar funciona
el problema está en que como todo tiene que repetirse con el while la
lista está vacía para el 2do while jeje hay alguna forma de quitar de
la lista un objeto pero sin eliminarlo?
de seguro que es fácil pero no me doy cuenta :(
He intentado con copiar a otra lista, pero en la 2da iteración del
while ya está vacía, además no es la idea copir otra lista si no
remover en el primer for el objeto
para que en el 2do ya no se itere y no tenga que comparar si es el
mismo y además será mucho más rápido
gracias :)
--
lopz es libre, usa --> GNU/linux gentoo
+--[RSA 2048]--+
| ..o.o=+ |
| o =o*.+ |
| . . *oO . |
| .EBoo |
| o.S |
+--[lopz.org]--+
Más información sobre la lista de distribución Python-es