Страницы

Поиск по вопросам

среда, 4 марта 2020 г.

Отсортировать список предложений по количеству букв и слов в python 2.7

#python #сортировка #python_27


Начинаю учить Python 2.7. Надо отсортировать список предложений по количеству букв
и слов. song - собственно сам файл со списком.

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

song = sys.argv[1]
w = open(song)
for line in sorted(w, key = int(len(line)))   
    print line

    


Ответы

Ответ 1



Параметр key должен быть функцией, принимающей текущий элемент и возвращающей значение, по которому сортируем. В данном случае достаточно просто len (приведение длины к целому излишне, т.к. len и так возвращает целое число): song = sys.argv[1] w = open(song) for line in sorted(w, key=len) print line В более сложных случаях сортировки может понадобиться создать lambda-функцию (или даже выносить код в отдельную именованную функцию). Для сортировки по количеству слов можно разбивать строку по пробельным символам с помощью метода строки split, и сортировать по количеству полученных кусков: song = sys.argv[1] w = open(song) for line in sorted(w, key=lambda x: len(x.split())) print line Чтобы отсортировать строки по количеству слов, а слова в строках по количеству букв, можно сделать так: Сначала просто создаем список строк, каждую строку разбиваем на слова: lines = [line.rstrip().split() for line in file] Добавляем сортировку слов внутри строк (это та же строка, просто добавили сортировку): lines = [sorted(line.rstrip().split(), key=len) for line in file] Добавляем сортировку строк по количеству слов (заменяю генератор списка на итератор - круглые скобки вместо квадратных): lines = sorted((sorted(line.rstrip().split(), key=len) for line in file), key=len) Т.к. строки уже разбиты на слова, то еще раз делать split не нужно, а просто сортируем по длине списка. Ну и при выводе на экран собираем списки слов обратно в целые строки: for line in lines: print ' '.join(line) Дополнение. Как правильно заметил jfs в комментариях к ответу, если файл сохранен например в utf-8 (вообще в любой не однобайтовой кодировке), то будет не подсчет символов, а подсчет байт, плюс не будет работать разбивка по юникодным пробельным символам. Чтобы открыть файл в нужной кодировке, нужно использовать функцию io.open(). При открытии будет использоваться кодировка системы по-умолчанию. Чтобы использовать конкретную кодировку, можно указать ее при открытии: import io ... w = io.open(song, encoding='utf-8')

Ответ 2



Чтобы отсортировать список предложений sentences по количеству слов: sentences.sort(key=word_count) где функция word_count() принимает предложение и возвращает количество слов в нём. Если вы ещё хотите, чтобы слова внутри отдельных предложений были отсортированы по количеству букв, то следует разбить каждое предложение на слова и отсортировать слова: words = get_words(sentence) words.sort(key=char_count) Здесь get_words() функция принимает предложение и возвращает список слов в нём. char_count() функция принимает слово и возвращает количество букв в нём. Как конкретно выглядят функции word_count, get_word, char_count зависит существенно от задачи. К примеру, если входной файл, заданный в командной строке, содержит предложения каждое на новой строке, а слова просто отделены пробелом, тогда чтобы отсортировать предложения по количеству слов в них, а слова внутри предложений по количеству букв: #!/usr/bin/env python import io import sys with io.open(sys.argv[1]) as file: sentences = file.read().splitlines() # NOTE: line ends are not included result = sorted([sorted(get_words(s), key=char_count) for s in sentences], key=word_count) for words in result: # for each sentence print(' '.join(words)) где: get_words = unicode.split # split on arbitrary whitespace word_count = len # number of items in the list of words char_count = len # unicode word length Замечания по коду: io.open() используется, чтобы текст как unicode прочитать, а не байты (используя locale.getpreferredencoding() кодировку). Количество байт в слове может не совпадать с количеством символов в нём. См. Длина строки считается неверно unicode.splitlines() возвращает список строк, убирая концы строк unicode.split() разбивает строку по произвольному пробелу (не только u' ', но к примеру и неразрывный пробел U+00A0 понимает). В качестве альтернативы, можно было бы регулярное выражение использовать, чтобы список слов получить: import re words = re.findall(r'\w+', sentence, flags=re.UNICODE) это полезно, если вы не хотите к примеру, пунктуацию рассматривать частью слов (если просто по пробелам разбить, то точки, запятые в словах остаются) word_count = len работает, так как каждое предложение как список слов представлено в коде unicode объект в Питоне является неизменяемой последовательностью символов (Unicode codepoints), поэтому char_count = len. То есть количество букв считается равным количеству символов в слове. Стоит заметить, что одно видимая буква, может из нескольких символов состоять: >>> len(u"ё") 2 >>> u"ё" u'\u0435\u0308' Для целей перемещения по тексту, для копирования в GUI мы бы не хотели только половину буквы получить. См. Разделить в Python 3 слово на символы Дополнительно, существуют так называемые "узкие" сборки python 2 исполняемого файла, в которых не-BMP символы такие как U+1F602 (FACE WITH TEARS OF JOY) в виде суррогатной пары представлены (абстракция нарушена — дефект в реализации). В "широких" сборках (часто на Linux) или на Питоне 3 этой проблемы не существует: индексация (Unicode) строк не разбивает символ (Unicode codepoint): >>> print(u'\U0001f602') 😂 >>> len(_) 1

Комментариев нет:

Отправить комментарий