Возвращать символы в строке в алфавитном порядке

Проблема

  
  • Возьмите строку и верните все входные символы в алфавитном порядке
  •   
  • Предположим, что никакие числа или знаки препинания не будут использоваться
  •   
  • Для одного и того же символа символы верхнего регистра должны быть возвращены перед строчными символами
  •   
  • Не используйте вспомогательный метод sorted
  •   
  • Не используйте библиотеки, не включенные в Python 3.6.1
  •   

Например, alphabetize(HelLo) должен возвращать eHLlo

Подход

  1. Создайте список из 26 элементов. Этот список будет представлять подсчеты (в верхнем регистре и строчные буквы) различных алфавитных символов, видимых через словарь
  2. Итерация через символы во входной строке
    1. Получить индекс для каждого символа, вычитая значения int символа нижнего регистра из значения int a
    2. Получить существующий счетчик для этого индекса & случай из подсчета Словарь
    3. Увеличить счетчик с помощью 1
  3. Инициализировать строку возврата
  4. Итерации через каждый элемент в списке
    1. Для каждого словаря /элемента, получите символ и получите прописные и строчные буквы
    2. Добавьте символы верхнего регистра в строку возврата
    3. Добавьте строчные символы в строку возврата
  5. Возвращает алфавитную строку

Обсуждение по вопросам разработки

Я знаю, что способ «Pythonic» достичь этого - это что-то вроде ''.join(sorted(myString))

Однако, поскольку кто-то пытается изучить Python, я хотел использовать это упражнение чтобы узнать больше о строках и символах в Python (например) против Googling с одним слоем (не в том, что с этим что-то не так).

Что меня беспокоит:

  • Должен ли это быть класс? Или это нормально, как автономный метод? (В виде кто-то более удобный в Java, вещи, которые не входят в классы сделайте меня нерационально непростым.)
  • Говоря об этом, в этом есть приличное количество вещей метод, должен ли я разбить его?
    • Если я решит разбить его, то какой способ «показать» некоторые функции будут использоваться другой функцией?
    • Я думаю, что у Python действительно нет понятия private vs. public, так что я _(some_method_name) здесь?
  • Какие еще элементы «Pythonic» мне не хватает (опять же, помимо использования метод sorted)?

Реализация

def alphabetize(value):
    uppercase_key = 'uppercase'
    lowercase_key = 'lowercase'

    character_counts = []
    for i in range(26):
        character_counts.append({uppercase_key: 0, lowercase_key: 0}.copy())

    for character in value:
        index = ord(character.lower()) - ord('a')
        counts = character_counts[index]
        key = uppercase_key if character.isupper() else lowercase_key

        count = counts[key]
        counts[key] = count + 1

    alphabetized = ''
    for index, counts in enumerate(character_counts):
        character = chr(ord('a') + index)
        uppercase_counts = counts[uppercase_key]
        lowercase_counts = counts[lowercase_key]
        for i in range(uppercase_counts):
            alphabetized += character.upper()
        for i in range(lowercase_counts):
            alphabetized += character

    return alphabetized
11 голосов | спросил Jae Bradley 23 AM00000050000002331 2017, 05:23:23

3 ответа


10
  

Какие еще элементы «Pythonic» мне не хватает (опять же, помимо использования отсортированного метода)?

Если вы хотите более широко использовать стандартную библиотеку, вы можете использовать collections.Counter вместе с константы алфавита string.ascii_uppercase и string.ascii_lowercase

Вещи также проще, если вы храните счеты в dict (map) вместо неявного map-by-ord() -value которые вы используете в настоящее время. Порядок отсчетов не имеет значения, просто порядок, в котором вы их выводите.

from collections import Counter
from itertools import chain
import string


def alphabetize(s):
    counts = Counter(s)

    return ''.join(
        char * counts[char]
        for char in chain(*zip(string.ascii_uppercase, string.ascii_lowercase))
    )

Строка counts = Counter(s) делает это:

counts = collections.defaultdict(int)

for char in s:
    counts[char] += 1

, где defaultdict (удобный класс) - это dict, который автоматически инициализирует значения на основе вашего конструктора, вместо того, чтобы бросать исключение для отсутствующих ключей.

chain(*zip(...)) сжимает буквы верхнего и нижнего регистра, затем сглаживает их с помощью chain() в один список, ['A', 'a', 'B', ...].


  

Если это класс?

Неа. Это имеет смысл как функция в Python, так как не имеет внешнего состояния.

  

Как человек, который более удобен в Java, вещи, которые не входят в классы, делают меня нерационально непростым.

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

ответил BenC 23 AM00000060000000431 2017, 06:55:04
5
  • Вызов copy() {uppercase_key: 0, lowercase_key: 0}.copy() является избыточным. copy() имел бы смысл, если бы вы назначили этот dict переменной где-то и добавляли эту переменную.

  • Не используйте +=, чтобы создать большую строку, это может привести к квадратичному времени. Рекомендуемый способ: создайте список такой строки, а затем присоедините их, используя str.join. Проверьте: Советы по производительности: Конкатенация строк .

  • count = counts[key]; counts[key] = count + 1 в основном counts[key] += 1.

ответил Ashwini Chaudhary 23 AM00000060000000031 2017, 06:01:00
0

ИЗМЕНИТЬ; Отказ от ответственности: я действительно понял предложение «вернуть все входные символы в алфавитном порядке» в качестве заданного вопроса, следовательно, мой ответ, который вернет только один символ каждого типа, присутствующего во входной строке.
Я оставил его как есть, так как он мог ответить на какой-то прецедент.


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

import string

def alphabetize(inputstr):
    inputset = set(inputstr)
    refset_caps = set (string.ascii_uppercase)
    refset_mins = set (string.ascii_lowercase)
    leftcaps = refset_caps -(refset_caps - inputset)
    leftmins = refset_mins -(refset_mins - inputset)
    finalstr = list(zip(leftcaps , leftmins))
    #finalstr = str(l).strip("[']").replace("', '","")
    #Line above should be used in case you need to return a string and not a list, you can adapt the replace input to keep commas, too.
    return finalstr

Объяснение 1: Сначала я думал о создании только одного набора, но это забывает, что набор не упорядочен сам по себе. С другой стороны, у них есть свойство nice, чтобы возвращать символы в порядке юникода, следовательно, в то время как

l = [a for tuple in zip(string.ascii_uppercase, string.ascii_lowercase) for a in tuple]

возвращает список в правильном порядке,

s = {a for tuple in zip(string.ascii_uppercase, string.ascii_lowercase) for a in tuple}

возвращает буквы в алфавитном порядке, затем minuscules в алфавитном порядке.

Итак, я просто делаю операции декомпозиции по каждому набору отдельно (я удаляю каждую ссылку, устанавливая разницу между ссылочным набором и набором из ввода, который оставляет в основном только набор из ввода, но упорядочен на этот раз для каждого класса символы (capitals /minuscules) и присоединяться к ним в zip и переключаться на список, который сохраняет порядок ввода.

Моя вторая альтернатива - это вариант по тому же принципу, используя только один набор для ссылки:     строка импорта

def alphabetize(inputstr):
    inputset = set(inputstr)
    prestr = [chrt for sublist in zip(string.ascii_uppercase , string.ascii_lowercase) for chrt in sublist]
    refset = set(prestr)
    leftchars = refset -(refset - inputset)

    finalstr = [character for character in inputset if character in leftchars ]
    #I could also have written directly  finalstr = [character for character in inputset if character not in (refset - inputset)]

    #finalstr = str(prestr2 ).strip("[']").replace("', '","")
    #Line above should be used in case you need to return a string and not a list, you can adapt the replace input to keep commas, too.

    return finalstr

Моя третья альтернатива работает лучше, для каждого случая:

import string

def alphabetize(inputstr):
    inputset = set(inputstr)
    prestr = [chrt for sublist in zip(string.ascii_uppercase , string.ascii_lowercase) for chrt in sublist]
    refset = set(prestr)
    for character in (refset - inputset):
        prestr.remove(character )      
    """but I guess it adds loads of complexity to the operation, as removing depends on length of the list -while here it is and always be limited- and is slower by conception than set operation"""

    finalstr = prestr.copy()  #or
    #finalstr = str(prestr2 ).strip("[']").replace("', '","")
    #Line above should be used in case you need to return a string and not a list, you can adapt the replace input to keep commas, too.

    return finalstr

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

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

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

Надеюсь на эту помощь.

Я хотел бы поразмышлять, но я не могу, я пишу с телефона.

ответил Ando Jurai 24 PM00000010000003731 2017, 13:05:37

Похожие вопросы

Популярные теги

security × 330linux × 316macos × 2827 × 268performance × 244command-line × 241sql-server × 235joomla-3.x × 222java × 189c++ × 186windows × 180cisco × 168bash × 158c# × 142gmail × 139arduino-uno × 139javascript × 134ssh × 133seo × 132mysql × 132