Форум сайта python.su
0
Доброго времени суток. Сам я программирую в java и немного в Delphi, а тут попросили сделать задачку на питоне. Задача следущая: есть набор русских слов в файле, разделённых пробелами, пунктуацией, а также числами. Необходимо подсчитать количество одинаковых слов и вывести их на консоль в отсортированном по алфавиту словаре в виде (слово, количество). Проблема оказалась в том, что для русской локали е и ё - абсоллютно одинаковые буквы, в то время, как в алфавите е идет перед ё, т. е. слово “ель” должно становиться перед словом “ёлка”. Пришлось искать возможности создания правил сортировки. Я обнаружил, что для питона 2 в функции сортировки есть ключ cmp для компаратора, но делать компаратор для кирилицы в питоне 2 мне показалось нетривиальной задачей. У питона 3 с UTF-8 дела обстоят получше, но компаратор, как таковой, в нём использовать уже нельзя. Зато там есть костыль в виде функции cmp_to_key, которым я в итоге и воспользовался. Вот что у меня получилось:
from codecs import open from functools import cmp_to_key from re import split text = open("load", "r", "utf-8") s = text.read() words = split('[\d\W]+', s) d = {} for w in words: if w != '': if w in d: d[w] += 1 else: d[w] = 1 items = list(d.items()) def comparator(a, b): x = str(a) y = str(b) t = len(x) if len(x) < len(y) else len(y) for j in range(t): if x[j] == y[j]: continue if x[j] != 'ё' and y[j] != 'ё': if x[j] < y[j]: return -1 else: return 1 elif x[j] == 'ё': if y[j] > 'е': return -1 else: return 1 elif y[j] == 'ё': if x[j] > 'е': return 1 else: return -1 if len(x) < len(y): return -1 elif len(x) > len(y): return 1 else: return 0 items.sort(key=cmp_to_key(comparator)) for i in items: print(i)
Офлайн
568
#!/usr/bin/env python # -* coding: utf-8 -*- d = [u'ё', u'ель', u'ёлочка', u'ёжик', u'ё моё', u'е', u'ельник', u'ежовый'] import sys print (sys.version) for i in sorted(d): print i
2.7.5+ (default, Sep 19 2013, 13:48:49)
[GCC 4.8.1]
е
ежовый
ель
ельник
ё
ё моё
ёжик
ёлочка
Отредактировано FishHook (Май 25, 2015 10:52:22)
Офлайн
186
Если не правильно, то это поможет:
sorted([u"а", u"ё", u"е"], key=ord)
Отредактировано Rodegast (Май 25, 2015 10:55:39)
Офлайн
53
Rodegast
>>> ord('е') 1077 >>> ord('ё') 1105
Офлайн
186
> в алфавите е идет перед ё
1077 < 1105
Разве что-то не так?
Офлайн
0
sanderпонятно, а ord('я') - 1103, т. е. ё идет вообще последней буквой.
>>> ord('е') 1077 >>> ord('ё') 1105
Rodegastа sorted(, key=ord) - выводит ‘е’, ‘я’, ‘ё’, т. е ё - последняя.
sorted(, key=ord)
FishHookтоже самое, если добавить в список слово на букву “я”, оно выведется перед словом на ё и потом, print i - это питон 2, в 3-м надо print(i), а я делаю на 3-м.
d = import sys print (sys.version) for i in sorted(d): print i
Отредактировано Pawl (Май 25, 2015 11:20:54)
Офлайн
568
Да, действительно, ord, кстати, не помогает.
Тупенько, зато работает
#!/usr/bin/env python # -* coding: utf-8 -*- d = [u'ё', u'ель', u'ямка', u'ёлочка', u'упырь', u'ёжик', u'ё моё', u'е', u'ельник', u'ежовый', u'ягель'] ALPHABET = {i[1]: i[0] for i in enumerate(u"абвгдеёжзийклмнопрстуфхцчшщъыьэюя")} for i in sorted(d, key=lambda x: ALPHABET[x[0].lower()]): print (i)
Отредактировано FishHook (Май 25, 2015 11:30:44)
Офлайн
186
Да похоже что Ё это слабое место юникода
Тогда как-то так:
idx = [u"а", u"ё", u"е", u"я"] sorted([u"а", u"ё", u"е"], key=lambda x: idx.index(x[0]))
Офлайн
0
FishHookпочему-то в таком виде
Тупенько, зато работает
from codecs import open from re import split text = open("load", "r", "utf-8") s = text.read() words = split('[\d\W]+', s) d = {} for w in words: if w != '': if w in d: d[w] += 1 else: d[w] = 1 items = list(d.items()) ALPHABET = {i[1]: i[0] for i in enumerate(u"абвгдеёжзийклмнопрстуфхцчшщъыьэюя")} for i in sorted(items, key=lambda x: ALPHABET[x[0].lower()]): print(i)
Traceback (most recent call last):
File “CUsers/Pawl/IdeaProjects/pyFirst/first.py”, line 18, in <module>
for i in sorted(items, key=lambda x: ALPHABET[x.lower()]):
File “CUsers/Pawl/IdeaProjects/pyFirst/first.py”, line 18, in <lambda>
for i in sorted(items, key=lambda x: ALPHABET[x.lower()]):
KeyError: ‘метла’
Офлайн
0
FishHookтак тоже такая же ошибка
Да похоже что Ё это слабое место юникода Тогда как-то так:
Офлайн