2011-12-24 5 views

Respuesta

8
v = [1,2,3,4,3,1,2] 
any([2,3] == v[i:i+2] for i in xrange(len(v) - 1)) 

Mientras que la versión de @ PaoloCapriotti hace el truco, éste es más rápido, ya que deja de analizar el v tan pronto como se encuentra una coincidencia.

+1

¿No será el empalme de crear una nueva lista secundaria cada vez? ¿No será 2 si es mejor? corrígeme si estoy equivocado. – st0le

+0

Creo que 'v [i: i + 2]' solo ve los elementos de la lista. – eumiro

+2

@eumiro Tu creencia es incorrecta :-) List slices create new lists. Por ejemplo, ese es el mecanismo detrás del modismo para crear una copia de lista: '' c = s [:] ''. –

2
[2, 3] in [v[i:i+2] for i in range(len(v) - 1)] 
1

En general, es imposible sin iterar sobre todos los valores. Después de todo, una lista de mil elementos puede terminar en [.., 2, 3].

En casos especiales, hay atajos. ¿Los valores están siempre ordenados y siempre está buscando un valor específico? Si es así, puede, por ejemplo, usa una búsqueda binaria para encontrar el valor y luego compáralo con el siguiente valor. Si los valores están desordenados, no hay atajos. Si está buscando dos valores posteriores, no hay atajos. Para los casos intermedios, puede haber un atajo.

3

Esto es probablemente un poco de una manera indirecta de hacerlo, pero se puede usar (con su variable v arriba):

' 2, 3' in str(v) 
+5

¿Estás seguro de que el patrón "12, 3" no existe? – DSM

+1

@ uosɐs: editó la respuesta para incluir un espacio adicional para tratar de evitar el problema que señalé, pero todavía no funciona. Su versión no coincidirá con un 2,3 justo al comienzo de la secuencia (porque el carácter anterior al 2 será [, no un espacio). – DSM

+1

Lamento editarlo. 1) no era mío para editar, solo estaba feliz, 2) confundió tu comentario, 3) no es una solución eficiente. Pero en respuesta a su comentario aquí, la manera en que la lista se convierte en una cadena es importante aquí, sí. Si hubiera un espacio líder y sin corchetes, funcionaría. –

1

Vas a necesitar un bucle.

A diferencia de las cadenas de Python que admiten una prueba de subsecuencia mediante el operador en, las listas de Python no tienen una prueba de subsecuencia incorporada.

0

Si escribir la lista ocurre con mucha menos frecuencia que la lectura de ella, tal vez se podría construir un árbol de prefijos sobre escritura. [1] tendría un nodo secundario [2], [2] tendría un [3] y un [3] un [4]. Con un conjunto de datos más complejo, el árbol sería más útil. Tendría una profundidad de 2 en su caso y se indexaría en el elemento inicial de su secuencia de búsqueda.

todavía serías asisten cada nodo, pero sólo una vez durante la vida de la secuencia buscada, si sólo de adición. A medida que agrega un elemento, debe actualizar el árbol para incluir el subsequnce si no está presente. Entonces las lecturas se reducen a un máximo de O (2 * k) donde k es la cantidad de elementos únicos. En el caso de los dígitos, son 20 lecturas máximas para probar si una secuencia está en la lista.

ventaja La velocidad viene de precomputen la longitud-2 subsecuencias de la lista contiene y de la eliminación de duplicados. También se adapta bien a longitudes más largas. O (profundidad * k) el peor caso. Aún mejor si se emplean hashtables.

2
v = [1,2,3,4,3,1,2] 

def find(x,y,v): 
     return (x,y) in zip(v,v[1:]) 

print find(2,3,v) 
print find(1,4,v) 
0

Sé que ya está satisfecho con uno de la respuesta de en este post pero, puede intentar con los siguientes

>>> v = [1,2,3,4,3,1,2] 
def InList(v,(i,j)): 
    start=1 
    try: 
     while True: 
      if v[v.index(i,start)+1]==j and v[v.index(j,start)-1]==i: 
       return True 
      start=v.index(i)+1 
    except IndexError: 
     return False 
    except ValueError: 
     return False 


>>> InList(v,(2,3)) 
True 
>>> InList(v,(4,5)) 
False 
>>> InList(v,(1,2)) 
True 
>>> InList(v,(12,2)) 
False 
>>> InList(v,(3,1)) 
True 

Ok curiosidad lo mejor de mí y así que quería probar cómo lo hace aplicación realiza con la aplicación más rápida publicado

>>> stmt1=""" 
v = [1,2,3,4,3,1,2] 
def InList(v,(i,j)): 
    start=1 
    try: 
     while True: 
      if v[v.index(i,start)+1]==j and v[v.index(j,start)-1]==i: 
       return True 
      start=v.index(i)+1 
    except IndexError: 
     return False 
    except ValueError: 
     return False 
InList(v,(2,3)) 
InList(v,(4,5)) 
InList(v,(1,2)) 
InList(v,(12,2)) 
""" 
>>> stmt2=""" 
v = [1,2,3,4,3,1,2] 
def InList(v,(x,y)): 
    any([x,y] == v[i:i+2] for i in xrange(len(v) - 1)) 
InList(v,(2,3)) 
InList(v,(4,5)) 
InList(v,(1,2)) 
InList(v,(12,2)) 
""" 
>>> t1=timeit.Timer(stmt=stmt1) 
>>> t2=timeit.Timer(stmt=stmt2) 
>>> print "%.2f usec/pass" % (1000000 * t1.timeit(number=100000)/100000) 
13.67 usec/pass 
>>> print "%.2f usec/pass" % (1000000 * t2.timeit(number=100000)/100000) 
20.67 usec/pass 
>>> 

Gosh esta es una forma rápida

Nota ** Gracias Michael por señalarlo. Lo he corregido y aquí está mi solución actualizada.

+0

Esto no funcionará si hay un ejemplo de (i, _not j_) antes de '(i, j)'. –

+0

@MichaelHoffman, muchas gracias por señalarlo. Lo he corregido Es posible que desee echar un vistazo. – Abhijit

0

La respuesta de eumiro gana por elegancia, pero si necesita algo aún más rápido, puede aprovechar el método integrado list.index() que ahorra tiempo en la iteración de toda la lista.

v = [1,2,3,4,3,1,2] 

def f1(items): 
    return any([2,3] == v[i:i+2] for i in xrange(len(v) - 1)) 

def f2(items): 
    i = 0 
    index = items.index 
    try: 
     while 1: 
      i = index(2, i) + 1 
      if items[i] == 3: 
       return True 
    except IndexError: 
     return False 

from timeit import repeat  
print "f1", min(repeat("f1(v)", "from __main__ import f1, v", number=1000)) 
print "f2", min(repeat("f2(v)", "from __main__ import f2, v", number=1000)) 

Cuando ejecuto esto, me sale:

f1 0.00300002098083 
f2 0.0 

Esto debería ser aún más rápido cuando el partido no es tan cerca del principio de la lista.

1

Puede usar el Boyer-Moore algorithm para una aceleración totalmente innecesaria. El caso general es un poco difícil, pero es sencillo si solo buscas un par.

def find_pair(seq, a, b): 
    i = 1 
    while i < len(seq): 
     if seq[i] == b and seq[i - 1] == a: return i - 1 
     i += 2 - (seq[i] == a) 

print find_pair([1, 5, 3, 4, 3, 1, 2, 3, 3], 2, 3) 
+0

En la mayoría de los casos, la velocidad de 'list.index()' incorporada de Python debería anular todas las ventajas obtenidas implementando Boyer-Moore en Python puro. –

+0

Es cierto, esta respuesta fue una especie de broma :) –

2

Tal vez aún más simple:

a = range(100) 
exists = (55,56) in zip(a, a[1:]) 
Cuestiones relacionadas