Intentando crear sublistas a partir de la lista en función de los elementos de inicio y finalización. No puedo obtener todas las apariciones de elementos de inicio y finalización

lst  = ['value0','<!program start>','value1','value2','<!program end>',
        'value3','<!program start>','value4','<!program end>','value5']

Salida esperada:

[['value0'],['<!program start>','value1','value2','<!program end>'],
 ['value3'],['<!program start>','value4','<!program end>'],['value5']]

Código:

start_idx = lst.index('<!program start>')
end_idx = lst.index('<!program end>')
final_result = lst[:start_idx] + [lst[start_idx:end_idx+1]] + lst[end_idx+1:]
print(final_result)
1
Jack 13 jul. 2021 a las 00:03

6 respuestas

La mejor respuesta

Usando iteración:

lst = ['value0', '<!program start>', 'value1', 'value2', '<!program end>',
       'value3', '<!program start>', 'value4', '<!program end>', 'value5']

res = []
start = False
temp = []

for item in lst:
    if item == '<!program start>':
        start = True
        temp.append(item)

    elif item == '<!program end>':
        start = False
        temp.append(item)
        res.append(temp)
        temp = []

    elif start:
        temp.append(item)
    else:
        res.append([item])

print(res)

Salida:

[['value0'], ['<!program start>', 'value1', 'value2', '<!program end>'], ['value3'], ['<!program start>', 'value4', '<!program end>'], ['value5']]

Con la bandera start manejé si el elemento está en el medio de la etiqueta de inicio y cierre o no.

1
SorousH Bakhtiary 12 jul. 2021 a las 21:28

Puede procesar los datos con un FSM relativamente simple (Máquina de estado finito):

def fsm(lst):
    result = []

    state = 0
    for elem in lst:
        if state == 0:
            result.append([elem])
            state = 1
        elif state == 1:
            if elem == '<!program start>':
                subl = [elem]
                state = 2
            else:
                break  # End of pattern.
        elif state == 2:
            subl.append(elem)
            if elem == '<!program end>':
                result.append(subl)
                state = 0

    return result


lst  = ['value0','<!program start>','value1','value2','<!program end>',
        'value3','<!program start>','value4','<!program end>','value5']

print(fsm(lst))

2
martineau 12 jul. 2021 a las 21:59

No es tan genial como tu one-liner, pero parece que funciona:

def process(input_list, start, end):
    output = []
    while len(input_list) != 0:
        if input_list[0] != start:
            # This isn't a start token, so just add it to the output
            output.append([input_list[0]])
            input_list = input_list[1:]
            continue

        # Looks like we've found a start token, look for the end
        # associated with it and append that. NOTE: You could
        # try/except here if you didn't know that the end token was
        # actually there.
        end_index = input_list.index(end)
        output.append(input_list[:end_index + 1])
        input_list = input_list[end_index + 1:]
    return output

Entiendo:

[['value0'],
 ['<!program start>', 'value1', 'value2', '<!program end>'],
 ['value3'],
 ['<!program start>', 'value4', '<!program end>'],
 ['value5']]

Como la salida que me parece correcta

0
mattlangford 12 jul. 2021 a las 21:24

El problema con su código es que el índice devuelve el primer índice visto y no todos los índices. pero se puede hacer simplemente usando bucles while.

final_list = []
i = 0
while i < len(lst):
    inner_list = []
    word = lst[i]
    if word == "<!program start>":
        while word != '<!program end>':                  
            word = lst[i]
            inner_list.append(word)
            i += 1    
    else:
        inner_list.append(word)
        i += 1
    final_list.append(inner_list)

print(final_list)
0
Issac Abraham 12 jul. 2021 a las 21:36

Solución similar con bucles while anidados.

test_list = ['value0','<!program start>','value1','value2','<!program end>',
        'value3','<!program start>','value4','<!program end>','value5']

answer_list = []
i = 0
while i < len(test_list):
    if test_list[i] == '<!program start>':
        sublist = []
        while test_list[i] != '<!program end>':
            sublist.append(test_list[i])
            i += 1
    elif test_list[i] == '<!program end>':
        sublist.append(test_list[i])
        answer_list.append(sublist)
        i += 1
    else:
        answer_list.append(test_list[i])
        i += 1

print(answer_list)

Produce:

['value0', ['<!program start>', 'value1', 'value2', '<!program end>'], 'value3', ['<!program start>', 'value4', '<!program end>'], 'value5']
0
Andrew 12 jul. 2021 a las 21:55

En realidad, existen algunos enfoques integrales interesantes que utilizan el procesamiento básico de str y list.

Por ejemplo, primero puede separar su lst en chunks según una subcadena generalizada de las etiquetas de inicio y finalización:

chunks = [s for s in " ".join(lst).split("<!program ")]

Estos fragmentos contienen inherentemente las características que distinguen entre elementos individuales y elementos entre etiquetas.

Una composición de lista es una forma agradable y elegante de obtener el resultado deseado:

output = [[s.strip('end> ')] if not s.startswith('start>') else ["<!program start>"] + s.strip("start> ").split() + ["<!program end>"] for s in chunks]
0
Max Shouman 12 jul. 2021 a las 22:23