Removing item in list during loop

痞子三分冷 提交于 2021-02-05 12:26:02

问题


I have the code below. I'm trying to remove two strings from lists predict strings and test strings if one of them has been found in the other. The issue is that I have to split up each of them and check if there is a "portion" of one string inside the other. If there is then I just say there is a match and then delete both strings from the list so they are no longer iterated over.

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

I get the above error though and I am assuming this is because I can't delete the string from test_strings since it is being iterated over? Is there a way around this?

Thanks

    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)

Example input:

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

so I want there to be a match between hello/there and hello/there/mister and for them to be removed from the list when doing the next comparison.

After one iteration I expect it to be:

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

After the second iteration I expect it to be:

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

回答1:


You should never try to modify an iterable while you're iterating over it, which is still effectively what you're trying to do. Make a set to keep track of your matches, then remove those elements at the end.

Also, your line for string in split_string: isn't really doing anything. You're not using the variable string. Either remove that loop, or change your code so that you're using string.

You can use augmented assignment to increase the value of 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)



回答2:


From your code it seems likely that two split_strings match the same test_string. The first time through the loop removes test_string, the second time tries to do so but can't, since it's already removed!

You can try breaking out of the inner for loop if it finds a match, or use any instead.

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)


来源:https://stackoverflow.com/questions/43357816/removing-item-in-list-during-loop

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!