Eliminación del elemento en la lista durante el bucle

Tengo el código de abajo. Estoy tratando de eliminar dos cadenas de listas. predict strings y test strings si uno de ellos ha sido encontrado en el otro. El problema es que tengo que dividir cada uno de ellos y comprobar si hay una "porción" de una cadena dentro de la otra. Si hay entonces solo digo que hay una coincidencia y luego eliminar ambas cadenas de la lista así que ya no están iterados.

ValueError: list.remove(x): x not in list

Pero tengo el error anterior y estoy suponiendo que esto es porque no puedo borrar la cadena de test_strings ya que está siendo iterado encima? ¿Hay alguna manera de hacerlo?

Gracias.

    for test_string in test_strings[:]:
        for predict_string in predict_strings[:]:
            split_string = predict_string.split('/')
            for string in split_string:
                if (split_string in test_string):
                    no_matches = no_matches + 1
                    # Found match so remove both
                    test_strings.remove(test_string)
                    predict_strings.remove(predict_string)

Ejemplo de entrada:

test_strings = ['hello/there', 'what/is/up', 'yo/do/di/doodle', 'ding/dong/darn']
predict_strings =['hello/there/mister', 'interesting/what/that/is']

así que quiero que haya una coincidencia entre hola / alla y hola / alla / musgo y para que sean eliminados de la lista al hacer la próxima comparación.

Después de una iteración Espero que sea:

test_strings == ['what/is/up', 'yo/do/di/doodle', 'ding/dong/darn']
predict_strings == ['interesting/what/that/is']

Después de la segunda iteración espero que sea:

test_strings == ['yo/do/di/doodle', 'ding/dong/darn']
predict_strings == []

Pregunta hecha hace 7 años, 1 meses, 5 días - Por geekguru


4 Respuestas:

  • Usted nunca debe tratar de modificar un iterable mientras usted está iterando sobre él, que es todavía eficaz lo que usted está tratando de hacer. Hacer un set para hacer un seguimiento de sus fósforos, y luego eliminar esos elementos al final.

    Además, tu línea for string in split_string: no está haciendo nada. No estás usando la variable string. O elimina ese bucle, o cambia tu código para que estés usando string.

    Puede utilizar la asignación aumentada para aumentar el valor de no_matches.

    no_matches = 0
    
    found_in_test = set()
    found_in_predict = set()
    
    for test_string in test_strings:
        test_set = set(test_string.split("/"))
        for predict_string in predict_strings:
            split_strings = set(predict_string.split("/"))
            if not split_strings.isdisjoint(test_set):
                no_matches += 1
                found_in_test.add(test_string)
                found_in_predict.add(predict_string)
    
    for element in found_in_test:
        test_strings.remove(element)
    
    for element in found_in_predict:
        predict_strings.remove(element)
    

    Respondida el Apr 11, 2017 a las 23:37 - por pixelpilot

    Votos positivos: 0 | Votos negativos: 0

  • De su código parece probable que dos split_strings match the same test_string. La primera vez a través del bucle elimina test_string, la segunda vez trata de hacerlo pero no puede, ya que ya está eliminado!

    Puedes intentarlo. breaking fuera del interior for bucle si encuentra una coincidencia, o uso any en lugar de eso.

    for test_string, predict_string in itertools.product(test_strings[:], predict_strings[:]):
        if any(s in test_string for s in predict_string.split('/')):
            no_matches += 1  # isn't this counter-intuitive?
            test_strings.remove(test_string)
            predict_strings.remove(predict_string)
    

    Respondida el Apr 11, 2017 a las 23:45 - por bytebard

    Votos positivos: 0 | Votos negativos: 0

  • El error que estás experimentando se debe a que estás modificando las listas test_strings y predict_strings mientras las estás recorriendo con un bucle for. Esto puede causar problemas ya que la longitud de la lista cambia a medida que eliminamos elementos de ella, lo cual puede romper el bucle.

    Para evitar este problema, puedes crear listas auxiliares para almacenar los elementos que deseas eliminar, y luego eliminar esos elementos después de finalizar el bucle.

    Aquí te dejo una versión corregida de tu código:

    python
    test_strings = ['hello/there', 'what/is/up', 'yo/do/di/doodle', 'ding/dong/darn']
    predict_strings = ['hello/there/mister', 'interesting/what/that/is']
    
    matches_to_remove = []
    
    for test_string in test_strings[:]:
        for predict_string in predict_strings[:]:
            split_string = predict_string.split('/')
            for string in split_string:
                if string in test_string:
                    no_matches = no_matches + 1
                    

    Encontrar coincidencia para ser eliminados después

    matches_to_remove.append(test_string) matches_to_remove.append(predict_string)

    Eliminar los elementos coincidentes

    for match in matches_to_remove: if match in test_strings: test_strings.remove(match) if match in predict_strings: predict_strings.remove(match)

    De esta manera, primero guardamos los elementos que deseamos eliminar en una lista auxiliar matches_to_remove, y luego eliminamos esos elementos después de que termina el bucle principal. Esto debería evitar el error que estabas experimentando.

    Respondida el Apr 12, 2017 a las 23:33 - por Gpt

    Votos positivos: 0 | Votos negativos: 0

  • Para eliminar un elemento de una lista mientras se recorre en Python, debes usar el método pop(index) en lugar de remove(element).

    Tu código modificado sería:

    python
    for test_string in test_strings[:]:
        for predict_string in predict_strings[:]:
            split_string = predict_string.split('/')
            for string in split_string:
                if (split_string in test_string):
                    no_matches = no_matches + 1
                    

    Encontrado una coincidencia, eliminar ambos

    test_strings.pop(test_strings.index(test_string)) predict_strings.pop(predict_strings.index(predict_string))

    El método pop(index) elimina el elemento en el índice especificado y devuelve ese elemento. En este caso, usamos index para obtener el índice del elemento que queremos eliminar.

    También es importante tener en cuenta que estás modificando las listas test_strings y predict_strings mientras las recorres. Para evitar problemas, siempre debes hacer una copia de la lista antes de modificarla, como:

    python
    for test_string in test_strings[:]:
        for predict_string in predict_strings[:]:
            ...
    

    Esto creará una copia de cada lista y te permitirá recorrer las copias sin modificar las listas originales.

    Respondida el Apr 12, 2017 a las 23:46 - por Gemini

    Votos positivos: 0 | Votos negativos: 0