Как можно более эффективно отобразить несколько символов в строке на отдельные символы? - PullRequest
3 голосов
/ 06 марта 2019

Я ищу более эффективный способ замены нескольких символов в строке одним символом.

В настоящее время мой код выглядит примерно так:

example = 'Accomodation'

VOWELS = 'aeiou'
CONSONANTS = 'bcdfghjklmnpqrstvwxyz'

output = ''
for char in example:
    if char in VOWELS:
        output += 'v'
    elif char in VOWELS.upper():
        output += 'V'
    elif char in CONSONANTS:
        ....

В конце концов, в случае примера он вернет Vccvcvcvcvvc.

Часть, которую я хотел бы сделать более эффективной, такова:

for char in example:
    if char in VOWELS:
        output += 'v'
    elif char in VOWELS.upper():
        output += 'V'
    elif char in CONSONANTS:
        ....

В идеале решение должно предусматривать отображение словаря символов в качестве ключа, а их значения - это список параметров. Э.Г.

replace_dict = {'v': VOWELS,
                'V': VOWELS.upper(),
                'c': CONSONANTS,
                ...

К сожалению, я не слишком знаком с map, но я ожидаю, что решение каким-то образом его использует.

Исследования

Я обнаружил похожую проблему: Python заменяет несколько символов в строке

Это означало бы, что мне нужно будет сделать что-то вроде:

target = 'Accomodation'
charset = 'aeioubcdfghjklmnpqrstvwxyzAEIOUBCDFGHJKLMNPQRSTVWXYZ'
key = 'vvvvvcccccccccccccccccccccVVVVVCCCCCCCCCCCCCCCCCCCCC'

Проблема для меня в том, что назначения не выглядят особенно ясными - несмотря на то, что это сохраняет блок операторов if / else. Кроме того, если бы я хотел добавить больше наборов символов, назначения стали бы все менее и менее читабельными, например, для разных наборов иностранных символов.


Может ли кто-нибудь, возможно, с большим количеством знаний о встроенных функциях, привести пример, который работает более эффективно / чисто, чем два приведенных выше примера?

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

Решение должно быть в python3.

Ответы [ 6 ]

3 голосов
/ 06 марта 2019

Существует более эффективный способ создания такого диктата:

example = 'Accomodation'

VOWELS = 'aeiou'
CONSONANTS = 'bcdfghjklmnpqrstvwxyz'

replace_dict = {
    **{v: 'v' for v in VOWELS},
    **{V: 'V' for V in VOWELS.upper()},
    **{c: 'c' for c in CONSONANTS}
}

print(''.join(replace_dict[s] for s in example))

# Vccvcvcvcvvc
2 голосов
/ 06 марта 2019

Как насчет обратного просмотра того, что вы делаете - должно быть масштабируемым

VOWELS = 'aeiou'
CONSONANTS = 'bcdfghjklmnpqrstvwxyz'
example = "Accomodation"
lookup_dict = {k: "v" for k in VOWELS}
lookup_dict.update({k: "c" for k in CONSONANTS})
lookup_dict.update({k: "V" for k in VOWELS.upper()})
lookup_dict.update({k: "C" for k in CONSONANTS.upper()})
''.join([lookup_dict[i] for i in example])
2 голосов
/ 06 марта 2019

Ваша replace_dict идея близка, но лучше «перевернуть» диктовку «наизнанку», т.е. превратить ее из {'v': 'aei', 'c': 'bc'} в {'a': 'v', 'e': 'v', 'b': 'c', ...}.

def get_replace_map_from_dict(replace_dict):
    replace_map = {}
    for cls, chars in replace_dict.items():
        replace_map.update(dict.fromkeys(chars, cls))
    return replace_map


def replace_with_map(s, replace_map):
    return "".join(replace_map.get(c, c) for c in s)


VOWELS = "aeiou"
CONSONANTS = "bcdfghjklmnpqrstvwxyz"


replace_map = get_replace_map_from_dict(
    {"v": VOWELS, "V": VOWELS.upper(), "c": CONSONANTS}
)
print(replace_with_map("Accommodation, thanks!", replace_map))

replace_with_map Функция выше сохраняет все несопоставленные символы (но вы можете изменить это со вторым параметром на .get() там), поэтому вывод будет

Vccvccvcvcvvc, ccvccc!

2 голосов
/ 06 марта 2019

Это один подход, использующий dict.

Пример:

example = 'Accomodation'

VOWELS = 'aeiou'
CONSONANTS = 'bcdfghjklmnpqrstvwxyz'

replace_dict = {'v': VOWELS,
                "V": VOWELS.upper(),
                "c": CONSONANTS
                }


print("".join(k for i in example 
              for k, v in replace_dict.items() if i in v
              )
        )

Выход:

Vccvcvcvcvvc
1 голос
/ 07 марта 2019

Я новичок в Python и мне так весело играть с ним. Давайте посмотрим, насколько хороши эти словари. Четыре алгоритма, которые были предложены здесь:

  1. Алекс (я) - стиль библиотеки C времени выполнения
  2. Адам - ​​соответствие четырем строкам
  3. Sanyash, Rakesh, Mortz - словарь (посмотреть таблицы)
  4. AKX - заменить на карту

Я внес небольшие исправления в предложенный код, чтобы сделать всю работу согласованной. Кроме того, я хотел сохранить объединенный код менее 100 строк, но получил 127 с четырьмя функциями для тестирования и пытался удовлетворить PyCharm количеством дополнительных пустых строк. Вот первые результаты гонки:

Place  Name Time   Total
1.      AKX 0.6777 16.5018 The winner of Gold medal!!!
2.  Sanyash 0.8874 21.5725 Slower by 31%
3.     Alex 0.9573 23.2569 Slower by 41%
4.     Adam 0.9584 23.2210 Slower by 41%

Затем я сделал небольшие улучшения в своем коде:

VOWELS_UP = VOWELS.upper()

def vowels_consonants0(example):
    output = ''
    for char in example:
        if char.isalpha():
            if char.islower():
                output += 'v' if char in VOWELS else 'c'
            else:
                output += 'V' if char in VOWELS_UP else 'C'
    return output

Это дало мне второе место:

Place  Name Time   Total

1.      AKX 0.6825 16.5331 The winner of Gold medal!!!
2.     Alex 0.7026 17.1036 Slower by  3%
3.  Sanyash 0.8557 20.8817 Slower by 25%
4.     Adam 0.9631 23.3327 Slower by 41%

Теперь мне нужно побрить эти 3% и занять первое место. Я проверил с текстом из романа Льва Толстого Война и мир

Оригинальный исходный код:

import time
import itertools

VOWELS = 'eaiouу'  # in order of letter frequency
CONSONANTS = 'bcdfghjklmnpqrstvwxyz'


def vowels_consonants0(example):
    output = ''
    for char in example:
        if char.isalpha():
            x = 'v' if char.lower() in VOWELS else 'c'
            output += x if char.islower() else x.upper()
    return output


def vowels_consonants1(example):
    output = ''
    for char in example:
        if char in VOWELS:
            output += 'v'
        elif char in VOWELS.upper():
            output += 'V'
        elif char in CONSONANTS:
            output += 'c'
        elif char in CONSONANTS.upper():
            output += 'C'
    return output


def vowels_consonants2(example):
    replace_dict = {
        **{v: 'v' for v in VOWELS},
        **{V: 'V' for V in VOWELS.upper()},
        **{c: 'c' for c in CONSONANTS},
        **{c: 'c' for c in CONSONANTS.upper()}
    }
    return ''.join(replace_dict[s] if s in replace_dict else '' for s in example)


def get_replace_map_from_dict(replace_dict):
    replace_map = {}
    for cls, chars in replace_dict.items():
        replace_map.update(dict.fromkeys(chars, cls))
    return replace_map


def replace_with_map(s, replace_map):
    return "".join(replace_map.get(c, c) for c in s)


replace_map = get_replace_map_from_dict(
    {"v": VOWELS, "V": VOWELS.upper(), "c": CONSONANTS, "C": CONSONANTS.upper()}
)


def vowels_consonants3(example):
    output = ''
    for char in example:
        if char in replace_map:
            output += char
    output = replace_with_map(output, replace_map)
    return output


def test(function, name):
    text = open(name, encoding='utf-8')
    t0 = time.perf_counter()
    line_number = 0
    char_number = 0
    vc_number = 0  # vowels and consonants
    while True:
        line_number += 1
        line = text.readline()
        if not line:
            break
        char_number += len(line)
        vc_line = function(line)
        vc_number += len(vc_line)
    t0 = time.perf_counter() - t0
    text.close()
    return t0, line_number, char_number, vc_number


tests = [vowels_consonants0, vowels_consonants1, vowels_consonants2, vowels_consonants3]
names = ["Alex", "Adam", "Sanyash", "AKX"]
best_time = float('inf')
run_times = [best_time for _ in tests]
sum_times = [0.0 for _ in tests]
show_result = [True for _ in tests]

print("\n!!! Start the race by permutation with no repetitions now ...\n")
print("  * - best time in race so far")
print("  + - personal best time\n")
print("Note  Name Time (Permutation)")

products = itertools.permutations([0, 1, 2, 3])

for p in list(products):
    print(p)
    for n in p:
        clock, lines, chars, vcs = test(tests[n], 'war_peace.txt')
        sum_times[n] += clock
        note = " "
        if clock < run_times[n]:
            run_times[n] = clock
            note = "+"  # Improved personal best time
        if clock < best_time:
            best_time = clock
            note = "*"  # Improved total best time
        print("%s %8s %6.4f" % (note, names[n], clock), end="")
        if show_result[n]:
            show_result[n] = False
            print("  Lines:", lines, "Characters:", chars, "Letters:", vcs)
        else:
            print()
print("\n!!! Finish !!! and the winner by the best run time is ...\n")
print("Place  Name Time   Total")
i = 0
for n in sorted(range(len(run_times)), key=run_times.__getitem__):
    i += 1
    t = run_times[n]
    print("%d. %8s %.4f %.4f " % (i, names[n], t, sum_times[n]), end="")
    if i == 1:
        print("The winner of Gold medal!!!")
    else:
        print("Slower by %2d%%" % (round(100.0 * (t - best_time)/best_time)))
1 голос
/ 06 марта 2019

Попробуйте это. Не нуждается в CONSONANTS и работает не только с английскими, но и с русскими буквами (я был удивлен):

example = 'AccomodatioNеёэыуюяЕЁЭЫуюяРаботает'
VOWELS = 'aeiouуаоиеёэыуюя'

output = ''
for char in example:
    if char.isalpha():
        x = 'v' if char.lower() in VOWELS else 'c'
        output += x if char.islower() else x.upper()

print(output)

VccvcvcvcvvCvvvvvvvVVVVvvvCvcvcvvc

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