вызов функции преобразования списка из буквенных символов в числовые - PullRequest
2 голосов
/ 31 марта 2020

Я пытаюсь реализовать алгоритм Soundex вручную, и для этого необходимо преобразовать буквенные текстовые символы в числовые c текстовые символы. Я определил следующую функцию:

import re

def sub_pattern(text):
    sub = [str(i) for i in range(1,4)]
    string = text

    abc = re.compile('[abc]')
    xyz = re.compile('[xyz]')

    encode = [abc, xyz]
    encode_iter = iter(encode)

    alpha_search = re.compile('[a-zA-Z]')

    for i in sub:
        if alpha_search.search(string):
            pattern = next(encode_iter)
            string = pattern.sub(i, string)
        else:
            return(string)

Эта функция будет кодировать abc символов в 1 и xyz символов в 2. Тем не менее, это работает только для одной строки, и мне нужно передать список строк в функцию. Я получил результаты, которые хочу использовать:

list(map(sub_pattern, ['aab', 'axy', 'bzz']

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

def sub_pattern(text_list):
    all_encoded = []
    sub = [str(i) for i in range(1,4)]

    abc = re.compile('[abc]')
    xyz = re.compile('[xyz]')

    encode = [abc, xyz]
    encode_iter = iter(encode)

    alpha_search = re.compile('[a-zA-Z]')

    for string in text_list:
        for i in sub:
            if alpha_search.search(string):
                pattern = next(encode_iter)
                string = pattern.sub(i, string)
            else:
                all_encoded.append(string)

Несколько замечаний:

  1. Поскольку я реализую алгоритм Soundex, порядок текста при его кодировании имеет значение. Я бы предпочел обновить строковый символ по его первоначальному индексу, чтобы избежать необходимости реорганизовывать его впоследствии. Другими словами, вы не можете выполнять какую-либо сортировку строки ... Я создал итератор для постепенного обновления строки, и он получает следующий шаблон regex, только если все символы еще не были преобразованы.
  2. Эта функция будет частью двух пользовательских классов, которые я создаю. Оба будут вызывать метод __iter__, чтобы я мог создать итерацию. Вот почему я использую функцию iter() для создания итерации, потому что она создаст новый экземпляр, если итератор автоматически.

Я знаю, это может показаться тривиальным вопросом относительно того, что я делаю, но я застрял.

Заранее спасибо.

Ответы [ 2 ]

1 голос
/ 01 апреля 2020

Как насчет рекурсивного использования вашей собственной функции? Вы можете сохранить оригинал точно таким, какой он есть, если вам это нужно:

import re

def sub_pattern(text):
    if isinstance(text, str):
        sub = [str(i) for i in range(1,4)]
        string = text

        abc = re.compile('[abc]')
        xyz = re.compile('[xyz]')

        encode = [abc, xyz]
        encode_iter = iter(encode)

        alpha_search = re.compile('[a-zA-Z]')

        for i in sub:
            if alpha_search.search(string):
                pattern = next(encode_iter)
                string = pattern.sub(i, string)
            else:
                return(string)
    else:
        return([sub_pattern(t) for t in text])


print(list(map(sub_pattern, ['aab', 'axy', 'bzz']))) # old version still works
print(sub_pattern(['aab', 'axy', 'bzz'])) # new version yields the same result

Если читатель не знает, что означает рекурсивно : вызов функции из внутри себя.

  • Это разрешено, потому что каждый вызов функции создает свою собственную область,
  • это может быть полезно, когда вы можете решить проблему, выполнив простую операцию несколько раз, или не можете предсказать заранее, сколько раз вам нужно выполнить это для достижения вашего решения, например, когда вам нужно распаковать вложенные структуры
  • , это определяется выбором базового случая (решения) и вызовом функции во всех других случаях пока не дойдете до базового варианта.
0 голосов
/ 01 апреля 2020

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

Я не уверен, что это то, что вы хотите, но я бы создал новый итератор для каждой строки, так как вы должны иметь возможность проходить через все это для каждого нового элемента. Я подправил некоторые имена переменных, которые также могут вызвать путаницу (строка и подпрограмма). Смотрите комментарии для изменений:

def sub_pattern(text_list):
    all_encoded = []
    digits = [str(i) for i in range(1,4)]

    abc = re.compile('[abc]')
    xyz = re.compile('[xyz]')

    encode = [abc, xyz]
    alpha_search = re.compile('[a-zA-Z]')

    for item in text_list:
        # Create new iterator for each string.
        encode_iter = iter(encode)
        for i in digits:
            if alpha_search.search(item):
                pattern = next(encode_iter)
                item = pattern.sub(i, item)
            else:
                all_encoded.append(item)
                # You likely want appending to end once no more letters can be found.
                break
    # Return encoded texts.
    return all_encoded

Тест:

print(sub_pattern(['aab', 'axy', 'bzz'])) # Output: ['111', '122', '122']
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...