[Python-es] Iterar 2 veces sobre 1 lista y comparar sus objetos lo mas rapido

Andrey Antoukh andsux en gmail.com
Lun Mayo 9 00:28:26 CEST 2011


Hola.
No se si estoy en lo cierto, pero puede que te haga falta un itertools.tee()
http://docs.python.org/library/itertools.html#itertools.tee

Un ejemplo simple:

a = [1,2,3,4,5,6]

from itertools import tee
first, second = tee(a, 2)

while True:
    try:
        first_next = next(first)
        second_next = next(second)
        if first_next == second_next:
            print first_next, second_next
    except StopIteration:
        break


Un saludo.
Andrei.

El 9 de mayo de 2011 00:17, lopz <lowlifebob en gmail.com> escribió:

> 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]--+
> _______________________________________________
> Python-es mailing list
> Python-es en python.org
> http://mail.python.org/mailman/listinfo/python-es
> FAQ: http://python-es-faq.wikidot.com/
>



-- 
http://twitter.com/andsux
http://www.niwi.be
****
http://www.freebsd.org/
http://www.postgresql.org/
http://www.python.org/
http://www.djangoproject.com/

"Linux is for people who hate Windows, BSD is for people who love UNIX"
"Social Engineer -> Because there is no patch for human stupidity"
------------ próxima parte ------------
Se ha borrado un adjunto en formato HTML...
URL: <http://mail.python.org/pipermail/python-es/attachments/20110509/76d5f859/attachment.html>


Más información sobre la lista de distribución Python-es