Re: [Python-es] Buscar índices de un array (que cump le condición) de forma eficiente

2010-03-04 Thread Daniel Garcia Moreno
2010/3/4 Kiko :
> Hola a todos.
>
> Estoy intentando buscar los indices de un subconjunto dentro de un conjunto
> y quiero saber si existe algo más eficiente que lo que he pensado.
>
> Me explico, por ejemplo, yo tengo:
>
> conjunto = range(1000, 1100, 1)
> subconjunto = range(1000, 1100, 3)
>
> Quiero saber la posición que tendría cada valor del subconjunto en el
> conjunto, es decir, subconjunto[0] tendría el índice 0 en conjunto
> (conjunto[0])), subconjunto[1] tendría el índice 3 en conjunto
> (conjunto[3])) y así.
>
> Estoy obteniendo los índices así
> indices = [conjunto.index(valor) for valor in subconjunto]
>
> Pero si conjunto y subconjunto son muy grandes se toma su tiempo.
>
> ¿Existe una forma más eficiente de obtener los índices?
>
> Muchas gracias a todos.
>

Según mis conocimientos en computación, esta búsqueda es de orden n^2.
Si el primer conjunto está ordenado, puede llegar a ser de orden
n*log(n) puesto que puedes hacer una búsqueda binaria en lugar de
conjunto.index(valor). Y creo que no vas a poder optimizar más por
ahí, porque la complejidad del problema es esa.
___
Python-es mailing list
Python-es@python.org
http://mail.python.org/mailman/listinfo/python-es
FAQ: http://python-es-faq.wikidot.com/


Re: [Python-es] Buscar índices de un array (que cump le condición) de forma eficiente

2010-03-04 Thread Daniel Garcia Moreno
2010/3/4 Kiko :
>
> El 4 de marzo de 2010 13:18, Juan Ignacio  escribió:
>>
>> Oppps, me falto la interrogante, era una pregunta :-) ¿Conjunto y
>> subconjunto están (o pueden estar) ordenados?
>
> Están ordenados para lo que quiero hacer.
>

Pues entonces puedes usar bisect en lugar de index:

import bisect

indices = [bisect.bisect(conjunto, valor) for valor in subconjunto]
___
Python-es mailing list
Python-es@python.org
http://mail.python.org/mailman/listinfo/python-es
FAQ: http://python-es-faq.wikidot.com/


Re: [Python-es] Buscar índices de un array (que cump le condición) de forma eficiente

2010-03-04 Thread Pablo Angulo
Kiko escribió:
> Hola a todos.
>
> Estoy intentando buscar los indices de un subconjunto dentro de un
> conjunto y quiero saber si existe algo más eficiente que lo que he
> pensado.
>
> Me explico, por ejemplo, yo tengo:
>
> conjunto = range(1000, 1100, 1)
> subconjunto = range(1000, 1100, 3)
>
> Quiero saber la posición que tendría cada valor del subconjunto en el
> conjunto, es decir, subconjunto[0] tendría el índice 0 en conjunto
> (conjunto[0])), subconjunto[1] tendría el índice 3 en conjunto
> (conjunto[3])) y así.
>
> Estoy obteniendo los índices así
> indices = [conjunto.index(valor) for valor in subconjunto]
>
> Pero si conjunto y subconjunto son muy grandes se toma su tiempo.
>
> ¿Existe una forma más eficiente de obtener los índices?
si sabes que los elementos del subconjunto están ordenados dentro del
conjunto, no necesitas buscar en toda la lista cada vez, sino sólo desde
la última búsqueda

indices = []
ultimo = 0
for v in subconjunto:
ultimo += conjunto[ultimo:].index(v)
indices.append(ultimo)

[conjunto[j] for j in indices]==subconjunto
> True

También te puede interesar usar conjuntos, si no necesitas el orden de
los elementos.

Un saludo
___
Python-es mailing list
Python-es@python.org
http://mail.python.org/mailman/listinfo/python-es
FAQ: http://python-es-faq.wikidot.com/


Re: [Python-es] Buscar índices de un array (que cump le condición) de forma eficiente

2010-03-04 Thread Pablo Angulo
Te escribo a tí directamente porque la lista parece que no me acepta!!
Si los elementos de  subconjunto están ordenados dentro de conjunto, la
búsqueda es O(n):



si sabes que los elementos del subconjunto están ordenados dentro del
conjunto, no necesitas buscar en toda la lista cada vez, sino sólo desde
la última búsqueda

indices = []
ultimo = 0
for v in subconjunto:
ultimo += conjunto[ultimo:].index(v)
indices.append(ultimo)


___
Python-es mailing list
Python-es@python.org
http://mail.python.org/mailman/listinfo/python-es
FAQ: http://python-es-faq.wikidot.com/


Re: [Python-es] Buscar índices de un array (que cump le condición) de forma eficiente

2010-03-04 Thread Pablo Angulo
Daniel Garcia Moreno escribió:
>
> Según mis conocimientos en computación, esta búsqueda es de orden n^2.
> Si el primer conjunto está ordenado, puede llegar a ser de orden
> n*log(n) puesto que puedes hacer una búsqueda binaria en lugar de
> conjunto.index(valor). Y creo que no vas a poder optimizar más por
> ahí, porque la complejidad del problema es esa.
>   
Si la lista grande tiene N elementos y la pequeña M, puedes elegir entre
O(Mlog(N)), usando bisect. o O(N), con la técnica que te decía antes.
___
Python-es mailing list
Python-es@python.org
http://mail.python.org/mailman/listinfo/python-es
FAQ: http://python-es-faq.wikidot.com/


Re: [Python-es] Buscar índices de un array (que cump le condición) de forma eficiente

2010-03-04 Thread Daniel Garcia Moreno
2010/3/4 Pablo Angulo :
> Daniel Garcia Moreno escribió:
>>
>> Según mis conocimientos en computación, esta búsqueda es de orden n^2.
>> Si el primer conjunto está ordenado, puede llegar a ser de orden
>> n*log(n) puesto que puedes hacer una búsqueda binaria en lugar de
>> conjunto.index(valor). Y creo que no vas a poder optimizar más por
>> ahí, porque la complejidad del problema es esa.
>>
> Si la lista grande tiene N elementos y la pequeña M, puedes elegir entre
> O(Mlog(N)), usando bisect. o O(N), con la técnica que te decía antes.
>

O puedes combinar las dos, buscar desde el último indice en adelante
pero hacerlo con busqueda binaria.
___
Python-es mailing list
Python-es@python.org
http://mail.python.org/mailman/listinfo/python-es
FAQ: http://python-es-faq.wikidot.com/


Re: [Python-es] Buscar índices de un array (que cump le condición) de forma eficiente

2010-03-04 Thread Pablo Angulo
Pablo Angulo escribió:
> indices = []
> ultimo = 0
> for v in subconjunto:
> ultimo += conjunto[ultimo:].index(v)
> indices.append(ultimo)
>
> [conjunto[j] for j in indices]==subconjunto
>   
>
Lamento ser pesado, pero hay que hacer un cambio:

indices = []
ultimo = 0
for v in subconjunto:
ultimo += conjunto.index(v,ultimo)
indices.append(ultimo)

___
Python-es mailing list
Python-es@python.org
http://mail.python.org/mailman/listinfo/python-es
FAQ: http://python-es-faq.wikidot.com/


Re: [Python-es] Buscar índices de un array (que cump le condición) de forma eficiente

2010-03-04 Thread Pablo Angulo
Daniel Garcia Moreno escribió:
>
>> Si la lista grande tiene N elementos y la pequeña M, puedes elegir entre
>> O(Mlog(N)), usando bisect. o O(N), con la técnica que te decía antes.
>> 
> O puedes combinar las dos, buscar desde el último indice en adelante
> pero hacerlo con busqueda binaria.
Yo diría que ésto es también es O(M log(N)) en el peor caso (cuando el
subconjunto son los M primeros valores de conjunto)

log(N)+log(N-1)+...+log(N-M)=O(M log(N))
___
Python-es mailing list
Python-es@python.org
http://mail.python.org/mailman/listinfo/python-es
FAQ: http://python-es-faq.wikidot.com/


Re: [Python-es] Buscar índices de un array (que cump le condición) de forma eficiente

2010-03-04 Thread Pablo Angulo
Olemis Lang (Simelix) escribió:
> Aquí por ejemplo hay un caso que ilustra el hecho de no confiar
> demasiado en las estimaciones teóricas . Las estimaciones de Pablo et
> al se pueden ver afectadas por la eficiencia de la implementación del
> método index (el cual no me parece que sea muy O(1) que digamos, pero
> no tengo los detalles en la mano ...) . E.g. si fuera O(n), O(log(n))
> ... en el peor caso entonces todos los análisis anteriores no serían
> del todo precisos (CMIIW)
>   
index no es O(1), sino que tarda tanto como tenga que buscar. Si tiene
que recorrer toda la lista, será O(n). En este caso, el tiempo total es
O(n) porque no se pasa dos veces por el mismo elemento de conjunto, pero
eso no significa que index sea O(1).
___
Python-es mailing list
Python-es@python.org
http://mail.python.org/mailman/listinfo/python-es
FAQ: http://python-es-faq.wikidot.com/


Re: [Python-es] Buscar índices de un array (que cump le condición) de forma eficiente

2010-03-04 Thread Pablo Angulo
Kiko escribió:
> tiempo de la primera opción: 0.0149998664856
> for i in subconjunto:
> ultimo = conjunto.index(i, ultimo+1)
> indices.append(ultimo)
> Los primero 25 valores de indices = [0, 3, 6, 9, 12, 15, 18, 21, 24,
> 27, 30, 33, 36, 39, 42, 45, 48, 51, 54, 57, 60, 63, 66, 69, 72]
>
> tiempo de mi opción, la original: 41.2180001736
> indices1 = [conjunto.index(i) for i in subconjunto]
> Los primero 25 valores de indices1 = [0, 3, 6, 9, 12, 15, 18, 21, 24,
> 27, 30, 33, 36, 39, 42, 45, 48, 51, 54, 57, 60, 63, 66, 69, 72]
>
> tiempo de la tercera opción: 0.046313354
> indices2 = [bisect.bisect(conjunto, i) for i in subconjunto]
> Los primero 25 valores de indices2 = [1, 4, 7, 10, 13, 16, 19, 22, 25,
> 28, 31, 34, 37, 40, 43, 46, 49, 52, 55, 58, 61, 64, 67, 70, 73]
>
> Menos mal que he preguntado a los expertos.
>
> Muchas gracias por las mejoras. Tanto la primera opción como la
> tercera son infinitamente mejores que la mía y aceptables en tiempo usado.
Las mediciones de tiempo hay que tomarlas con cautela: si subconjunto es
mucho más pequeño que conjunto, entonces Mlog(N) es menor que N, y te
interesa usar el tercer método.
___
Python-es mailing list
Python-es@python.org
http://mail.python.org/mailman/listinfo/python-es
FAQ: http://python-es-faq.wikidot.com/


Re: [Python-es] Buscar índices de un array (que cump le condición) de forma eficiente

2010-03-04 Thread Pablo Angulo
Olemis Lang (Simelix) escribió:
> Si no es O(1) entonces sospecho que en
>
> {{{
> #!python
>
> ultimo = -1
>  for v in subconjunto:
>  ultimo = conjunto.index(v, ultimo+1)
>  yield ultimo
> }}}
>
> hay un ciclo `for` explícito más un ciclo implícito `index`


No lo sospeches: tiene que haber un bucle para encontrar el índice, pero
en cuanto encuentras el primer índice con ese valor, te sales del bucle.
¿Cuántas iteraciones haces del bucle en total? Bueno, puede que para
algún caso particular hagan falta muchas iteraciones, pero la suma de
todas las iteraciones no puede superar N: La primera iteración del bucle
"for v in subconjunto", recorres desde 0 hasta indice[0], luego desde
indice[1] hasta indice[2],... si sumas todas esas cantidades tienes:

(indice[0] - 0) + (indice[1]-indice[0]) + ... + (indice[M-1] -
indice[M-2]) = indice[M-1] < N
___
Python-es mailing list
Python-es@python.org
http://mail.python.org/mailman/listinfo/python-es
FAQ: http://python-es-faq.wikidot.com/


Re: [Python-es] Buscar índices de un array (que cump le condición) de forma eficiente

2010-03-04 Thread Pablo Angulo
Olemis Lang (Simelix) escribió:
> No me parece que `index` recuerde el último índice de la lista (no
> estamos hablando de iteradores ;o) entre dos llamadas diferentes para
> recomenzar la búsqueda de un nuevo elemento (¿ o es que funciona así
> internamente ?) ... 
Normalmente, index comienza desde el principio, pero justo por eso le
pasamos otro argumento más a index:
 
ultimo = conjunto.index(v, ultimo+1)
___
Python-es mailing list
Python-es@python.org
http://mail.python.org/mailman/listinfo/python-es
FAQ: http://python-es-faq.wikidot.com/