2010-04-18 25 views
9

¿Cuál es la forma más fácil de contar la repetición consecutiva más larga de un cierto carácter en una cadena? Por ejemplo, la repetición consecutiva más larga de "b" de la cadena siguiente:Contando la ocurrencia más larga de secuencia repetida en Python

my_str = "abcdefgfaabbbffbbbbbbfgbb" 

sería 6, ya que otras repeticiones consecutivas son más cortos ¿Cómo puedo hacer esto en Python (3 y 2, respectivamente.)?

Respuesta

9

¿Qué tal un ejemplo de expresiones regulares:

import re 
my_str = "abcdefgfaabbbffbbbbbbfgbb" 
len(max(re.compile("(b+b)*").findall(my_str))) #changed the regex from (b+b) to (b+b)* 
# max([len(i) for i in re.compile("(b+b)").findall(my_str)]) also works 

Editar, Mine vs interjays

x=timeit.Timer(stmt='import itertools;my_str = "abcdefgfaabbbffbbbbbbfgbb";max(len(list(y)) for (c,y) in itertools.groupby(my_str) if c=="b")') 
x.timeit() 
22.759046077728271 

x=timeit.Timer(stmt='import re;my_str = "abcdefgfaabbbffbbbbbbfgbb";len(max(re.compile("(b+b)").findall(my_str)))') 
x.timeit() 
8.4770550727844238 
+0

+1 para ayudar a restablecer parcialmente el valor de regexp en este Sitio, muy valiente. – doug

4

Aquí está mi método de conteo realmente aburrido, ineficiente, directo (Interjay es mucho mejor). Tenga en cuenta que escribí esto en este pequeño campo de texto, que no tiene un intérprete, así que no lo he probado, y puede haber cometido un error realmente tonto que una lectura de prueba no captó.

my_str = "abcdefgfaabbbffbbbbbbfgbb" 
last_char = "" 
current_seq_len = 0 
max_seq_len = 0 

for c in mystr: 
    if c == last_char: 
     current_seq_len += 1 
     if current_seq_len > max_seq_len: 
      max_seq_len = current_seq_len 
    else: 
     current_seq_len = 1 
     last_char = c 

print(max_seq_len) 
+1

Es posible que deba actualizar 'last_char' en algún lugar del circuito; aparte de eso, +1 por proporcionar la manera realmente * más fácil *: es el enfoque que requiere menos conceptos/habilidades del programador. Por cierto, no es "ineficiente": cualquier solución tendrá que ver todos los caracteres en la cadena para proporcionar el resultado correcto, por lo que su costo será al menos O (n): su enfoque tiene un costo de tiempo de O (n), así que es decentemente eficiente. Una ligera mejora de la eficiencia sería actualizar 'max_seq_len' en el bloque' else: ', por lo que se actualiza una vez por secuencia en lugar de una vez por carácter. –

+0

Bien, ignore mi punto acerca de actualizar 'last_char', Ignacio lo arregló;) –

+0

Gracias Ignacio;) (Sólo quise decir ineficiente en cuanto a la cantidad de tipeo que tiene que hacer) –

9

Aquí es una sola línea:

max(len(list(y)) for (c,y) in itertools.groupby(my_str) if c=='b') 

Explicación:

itertools.groupby habrá grupos de caracteres idénticos consecutivos de regreso, junto con un iterador para todos los elementos de ese grupo. Para cada uno de estos iteradores, len(list(y)) dará la cantidad de elementos en el grupo. Tomar el máximo de eso (para el personaje dado) dará el resultado requerido.

2

Uso de codificación de longitud de ejecución:

import numpy as NP 

signal = NP.array([4,5,6,7,3,4,3,5,5,5,5,3,4,2,8,9,0,1,2,8,8,8,0,9,1,3]) 

px, = NP.where(NP.ediff1d(signal) != 0) 
px = NP.r_[(0, px+1, [len(signal)])] 
# collect the run-lengths for each unique item in the signal 
rx = [ (m, n, signal[m]) for (m, n) in zip(px[:-1], px[1:]) if (n - m) > 1 ] 

# get longest: 
rx2 = [ (b-a, c) for (a, b, c) in rx ] 
rx2.sort(reverse=True) 

# returns: [(4, 5), (3, 8)], ie, '5' occurs 4 times consecutively, '8' occurs 3 times consecutively 
+0

No debería "if (n - m)> 1" be "if (n - m)> = 1" para detectar una carrera de longitud 1? –

+1

@carlo_hamalainen - no. no realmente interesado en detectar "longitudes de carrera" de 1. – doug

0

Aquí está mi código, No es tan eficiente, pero parece funcionar:

def LongCons(mystring): 
    dictionary = {} 
    CurrentCount = 0 
    latestchar = '' 

    for i in mystring: 
     if i == latestchar: 
      CurrentCount += 1 
      if dictionary.has_key(i): 
       if CurrentCount > dictionary[i]: 
        dictionary[i]=CurrentCount 
     else: 
      CurrentCount = 1 
      dictionary.update({i: CurrentCount}) 
      latestchar = i 
    k = max(dictionary, key=dictionary.get) 
    print(k, dictionary[k]) 
    return 
Cuestiones relacionadas