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

lopz lowlifebob en gmail.com
Lun Mayo 9 04:02:58 CEST 2011


El día 8 de mayo de 2011 18:28, Andrey Antoukh <andsux en gmail.com> escribió:
> Hola.

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.

Voy a probarlo, no conocía tee :O , toca leer, gracias :)

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



-- 
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