Как переместить строки в списке с определенной общей подстрокой в ​​новый список? - PullRequest
2 голосов
/ 27 июня 2019

Я пытаюсь создать два списка, где подстроки в скобках во втором списке никогда не появятся в первом списке.

Учитывая начальный список строк и пустой список:

word_list = ['{a==meliorate}>ed>','{a==meliorate}>s>','{a==meliorate}','{anew}','{annex}>ing>','{anvil}>ed>','{anvil}>ing>','{anvil}','<un<{ban}>ed>','<re<{write}']

new_list=[]

Я бы хотел разделить список слов, чтобы половина слов была добавлена ​​в новый список. Однако для заданного в скобках {substring}, если он найден в word_list, он не должен быть найден в new_list и наоборот.

Итак, мы бы получили:

word_list = ['{anew}','{anvil}>ed>','{anvil}>ing>','<re<{apply}','<un<{ban}>ed>']

new_list=['{a==meliorate}>ed>','{a==meliorate}>s>','{a==meliorate}','<re<{write}','{annex}>ing>']

Моя попытка до сих пор:

regex = re.compile('.*({[a-z]+}).*')
matches=[]

for element in word_list:
    m = re.search(regex, element)
    if m:
        root = m.group(1)
        matches.append(root)

while counter < len(word_list)/2:
    randroot = random.choice(matches) #select a random {root}
    indices = [i for i, e in enumerate(matches) if e == randroot] #get indices of all words with given root
    for index in indices: #for each index of root-aligned words, appends corresponding word 
        new_list = word_list.pop(index)

Однако мой вывод выглядит случайным: строки, содержащие элементы в квадратных скобках, появляются в обоих списках. Любая помощь очень ценится!

Ответы [ 2 ]

1 голос
/ 27 июня 2019

В другом ответе уже говорилось, что регулярное выражение не будет совпадать ни с одной строкой с "=" в них, и что ваше сравнение не приведет к вашему выводу, но совпадению вместо этого.

возможно, самая большая проблемав том, что когда вы извлекаете элемент из списка, вы меняете его длину и, следовательно, все индексы элементов внутри.Вот почему ваш вывод более случайный, чем вы ожидали.Если вы вставите ранний элемент, а затем попытаетесь вставить последний элемент, вы также столкнетесь с IndexError.

. Я настроил код, чтобы не полагаться на индексы.Вероятно, это лучший способ справиться с итерациями, которые меняют длину.

#!/usr/bin/env python3
import re
import random

word_list = ['{a==meliorate}>ed>','{a==meliorate}>s>','{a==meliorate}','{anew}','{annex}>ing>','{anvil}>ed>','{anvil}>ing>','{anvil}','<un<{ban}>ed>','<re<{write}']

new_list=[]

regex = re.compile(r".*({[a-z=]+}).*")
matches=[]

for element in word_list:
        m = re.search(regex, element)
        if m:
                root = m.group(1)
                matches.append(root)

target = len(word_list) / 2
while len(new_list) < target:
        randroot = random.choice(matches) # select a random {root}
        found_words = [w for w in word_list if randroot in w] # get all words with given root in them

        if len(found_words) > target - len(new_list):
                continue

        new_list.extend(found_words)
        word_list = [w for w in word_list if w not in new_list] # remove all the words we just added

print(word_list)
print(new_list)

Объяснение изменений: я просто добавил "=" в ваше регулярное выражение, чтобы поймать "a == мелиорат".Я установил цель как переменную, потому что длина word_list изменится.

Теперь я просто проверяю, находится ли совпадение в строках с word_list вместо того, чтобы искать точное совпадение.это не полностью защищенный от ошибок подход, но, глядя на ваши входные данные, я думаю, что здесь можно безопасно использовать.

Проверка if помогает нам удостовериться, что мы получаем четные длины для каждого списка,Например, мы не будем добавлять «== мелиорат», что происходит 3 раза ... если у нас есть только 2 слота для достижения цели.Однако будьте осторожны, если список не может быть равномерно разделен, это вызовет бесконечный цикл.

Мы добавляем найденные слова в new_list с помощью extend.И теперь мы перестраиваем word_list, исключая любые значения, найденные в new_list ..

Результат:

['{a==meliorate}>ed>', '{a==meliorate}>s>', '{a==meliorate}', '{anew}', '<un<{ban}>ed>']
['{annex}>ing>', '{anvil}>ed>', '{anvil}>ing>', '{anvil}', '<re<{write}']
1 голос
/ 27 июня 2019

Итак, для начала ваше регулярное выражение на самом деле не будет соответствовать всем вашим словам в скобках, как показано..*({[a-z]+}).* не будет соответствовать: {a==meliorate} Я бы почти предположил, что знаки равенства являются опечатками, но если нет - рассмотрите возможность замены {[a-z]+} на что-то вроде {.+}

Кроме этого, ваш генератор также имеетпроблема.i for i, e in enumerate(matches) if e == randroot на самом деле не будет проверять, соответствует ли слово корню, потому что вы видите, является ли слово корнем только и является ли оно.То есть e = {write} таким образом e != re{write}.Вместо этого вы должны выполнить проверку регулярных выражений для слов, которые вы тянете, чтобы увидеть, содержат ли они корень, а не корень.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...