2012-05-02 21 views
8

Esta es la forma de ejemplo, intentaré explicarla en palabras posteriores. Tengo una lista de romper una cadena ...Cómo procesar una cadena en una capa de sublistas

dicen

[a, a, a, b, a, a, b, a, c, a, b, a, a, c, a, c, a] 

donde b es los criterios 1 y c es 2 criterios

que quiero romperlo en una lista como esta:

[a, a, a, [b, a, a, [b, a, c], a, [b, a, a, c], a, c], a] 

por lo que quiero para procesar la cadena de tal manera que cuando voy a través de él, si el artículo que coincide con los criterios 1, abre una nueva lista, si el artículo coincide con los criterios 2, cerrar la lista de una Devuelve un nivel arriba.

He intentado hacer algo como esto, pero no está funcionando muy bien.

def sublist(self, l): 
    for line in list: 
    if not b: 
    self.data.append(line) 
    else: 
    sublist(l[line:])  #<----- not sure how to recurse it. 

que he visto la lista de irrumpir en la lista de tamaño iguales ante el stackoverflow, pero no una ruptura en la lista secundaria utilizando un conjunto de criterios.

Soy bastante nuevo en Python, por lo que no estoy muy familiarizado con las estructuras de datos y las herramientas de iterador.

Respuesta

10

Aquí van:

lst = "aaabaabacabaacaca" 

def go(it): 
    for x in it: 
     if x == 'b': 
      yield [x] + list(go(it)) 
     else: 
      yield x 
      if x == 'c': 
       break 


print list(go(iter(lst))) 
+2

Nice. Los generadores definitivamente simplifican la estructura recursiva. – Marcin

+0

(+1) ¡Buena solución! – NPE

+0

Tenga en cuenta que esto maneja un "flujo insuficiente" al finalizar la salida. Esto podría no ser lo que se quiere. – Marcin

1
addlist = [] 
alllists = [] 
for item in mylist: 
    if item == b: 
     newlist = [item] 
     addlist.append(newlist) 
     alllists.append(addlist) 
     addlist = newlist 
    elif item == c: 
     addlist.append(item) 
     addlist = alllists.pop() 
    else: 
     addlist.append(item) 

Lo anterior funcionará siempre y cuando sus bc y delimitadores están equilibrados; en particular, si tiene un exceso de c s, tendrá un subdesbordamiento de pila.

Aunque a menudo me gustan las soluciones recursivas, esto tiene la ventaja de hacer explícita la pila, que en este caso, en mi opinión, conduce a un código más fácil de asimilar.

0

El siguiente lo hará:

a, b, c = 1, 2, 3 

def sublist(l): 
    ret = [] 
    while l: 
    val = l.pop(0) 
    if val == b: 
     ret.append([val] + sublist(l)) 
    else: 
     ret.append(val) 
     if val == c: break 
    return ret 

l = [a, a, a, b, a, a, b, a, c, a, b, a, a, c, a, c, a] 
print l 
print sublist(l) 

Tenga en cuenta que esto tiene el efecto secundario de la modificación l. Es trivial cambiar eso haciendo una copia.

1

con una pila:

def parseList(inList): 
    stack = [[]] 
    for element in inList: 
     if element == 'b': 
      stack.append([element]) 
      stack[-2].append(stack[-1]) 
     elif element == 'c': 
      stack.pop().append(element) 
     else: 
      stack[-1].append(element) 
    return stack[0] 

Esto romperá si hay más 'c de que' de

+0

Esta solución no funciona, con el ejemplo en la pregunta de OP produce un 'IndexError: lista índice fuera de rango' –

+0

gracias Oscar, no lo probé antes de publicarlo. fijo. – sobel

0

En el estilo recursividad reales que podría hacer la b siguiendo:

x = yourlist 
i = 0 
def lets_parse(): 
    global i 
    fnlist = [] 
    while i < len(x) 
     if x[i] == 'c': 
      fnlist.append(x[i]) 
      i += 1 
     return fnlist 
     elif x[i] == 'b': 
      i += 1 
      f = lets_parse() 
      f.insert(0, 'b') 
      fnlist.append(f) 
     else: 
      fnlist.append(x[i]) 
      i += 1 
return fnlist 

print lets_parse() 

Tenga en cuenta el uso de globals. Varios críticos pueden objetarlo como un mal estilo de codificación.

+0

De hecho, es un mal estilo de codificación. En "recursión real" no necesita usar variables globales, el resultado se transmite como parámetros y devuelve valores de la función recursiva. –

0
import ast  
mylist = '[a, a, a, b, a, a, b, a, c, a, b, a, a, c, a, c, a]' 
mylist = mylist.replace('a','"a"') 
mylist = mylist.replace('b','["b"') 
mylist = mylist.replace('c','"c"]') 
print ast.literal_eval(mylist) 
#Output: 
['a', 'a', 'a', ['b', 'a', 'a', ['b', 'a', 'c'], 'a', ['b', 'a', 'a', 'c'], 'a', 'c'], 'a'] 
1

allí es muy agradable respuestas para esta pregunta, me gustó especialmente solución recursiva de thg435 utilizando generadores y solución iterativa de Marcin que añade elementos a las listas de referencia.

También me pareció inquietante que algunas soluciones modifiquen la lista de entrada o utilicen el estado global. Eso, en mi humilde opinión, va en contra del verdadero espíritu de una solución recursiva.A continuación se muestra mi intento de encontrar una solución recursiva puramente funcional en Python. Sin dudas, hay formas mucho más idiomáticas y eficientes de resolver este problema, pero quería escribir una respuesta ya que la habría escrito en un lenguaje de programación puramente funcional:

# lst: the list to be processed 
# acc: accumulated result 
# stk: temporary stack 
def process(lst, acc, stk): 
    if not lst: 
     return acc 
    elif lst[0] == 'b': 
     return process(lst[1:], [lst[0]], [acc] + stk) 
    elif lst[0] == 'c': 
     return process(lst[1:], stk[0] + [acc + [lst[0]]], stk[1:]) 
    else: 
     return process(lst[1:], acc + [lst[0]], stk) 

lst = ['a', 'a', 'a', 'b', 'a', 'a', 'b', 'a', 'c', 'a', 'b', 'a', 'a', 'c', 'a', 'c', 'a'] 
process(lst, [], []) 
> ['a', 'a', 'a', ['b', 'a', 'a', ['b', 'a', 'c'], 'a', ['b', 'a', 'a', 'c'], 'a', 'c'], 'a'] 

Algunos detalles a destacar:

  • no consumo variables locales o globales, las variables únicos parámetros de función para hacer el seguimiento del estado
  • no consumo operadores de asignación
  • Sin iteradores o loo ps se usan para atravesar la lista de entrada, solo recursión
  • Es una solución recursiva de cola, aunque eso es irrelevante en Python
  • Solo se utilizan expresiones; operaciones como append o extend (que devuelven None) se evitan
  • No hay listas siempre son modificados (incluyendo la lista de entrada), en lugar de nuevas listas se crean según sea necesario (utilizando rebanadas de matriz para eso)
  • Es un bien corto y elegante solución, pero eso podría ser una opinión subjetiva :)
Cuestiones relacionadas