Найти - Пользователи
Полная версия: сортировка русских слов компаратором
Начало » Python для новичков » сортировка русских слов компаратором
1 2 3 4 5
Pawl
FishHook
Да блин! sorted не изменяет исходный список, в вашей интерпретации эта операция бессмысленна.
Хорошо. Пусть такая операция имеет смысл только со списком. Так
from codecs import open
from re import split
text = open("load", "r", "utf-8")
s = text.read()
words = split('[\d\W]+', s)
words.remove('')
ALPHABET = {i[1]: i[0] for i in enumerate(u"абвгдеёжзийклмнопрстуфхцчшщъыьэюя")}
for i in sorted(words, key=lambda x: ALPHABET[x[0].lower()]):
    print(i)
Все слова из файла сортируются прекрасно. Но когда я делаю из сортированного списка словарь:
d = {}
for w in words:
    if w != '':
        if w in d:
            d[w] += 1
        else:
            d[w] = 1
items = list(d.items())
вся сортировка слетает нафиг и потом вот это
for i in items:
    print(i)
Выдаёт, что Бог на душу положит. Можно как-нибудь сделать сортированным не список, а именно словарь?
Иными словами, получается так:
('мёд', 1)
('муляж', 1)
('мороз', 1)
('метёлка', 1)
('ель', 2)
('ёжик', 1)
('ежевика', 3)
('емеля', 1)
('метла', 1)
('улитка', 3)
('ёлка', 3)
а я хочу, чтоб было так:
('ежевика', 3)
('ель', 2)
('емеля', 1)
('ёжик', 1)
('ёлка', 3)
('метёлка', 1)
('метла', 1)
('мёд', 1)
('мороз', 1)
('муляж', 1)
('улитка', 3)
Shaman
е ё ё моё ёжик ежовый ёлочка ель ельник упырь ягель ямка
Ну, тут “ёжик” идет перед “ежовый”, что не корректно, т. к. по алфавиту е идёт перед ё.
MiK
Pawl
Словарь это ассоциативный массив, его нельзя сортировать. Чтобы отсортировать словарь, из него нужно получить список и сортировать уже его.
Shaman
lst = [u'ё', u'ель', u'ямка', u'ёлочка', u'упырь', u'ёжик', u'ё моё', u'е',  u'ельник', u'ежовый', u'ягель']
class mytr:
    def __init__(self):
        abet = u' абвгдеёжзийклмнопрстуфхцчшщъыьэюя'
        self.td = {c: k for k, c in enumerate(abet)}
    def __call__(self, s):
        return tuple(self.td[c] for c in s.lower())
lst.sort(key=mytr())
print ' '.join(lst)
е ежовый ель ельник ё ё моё ёжик ёлочка упырь ягель ямка
Как-то так
FishHook
Pawl
Что-то мне подсказывает, что доку по питону вы почитать поленились. Хотя бы основные типы то надо понять: list, dict, set, tuple. Потратьте час времени на изучение этих четырех типов коллекций и станет гораздо проще.
Pawl
MiK
Pawl
Словарь это ассоциативный массив, его нельзя сортировать. Чтобы отсортировать словарь, из него нужно получить список и сортировать уже его.
Хорошо, а как мне это сделать? Нашел вариант:
od = collections.OrderedDict(sorted(d.items()))
, скрестил его с примером FishHook'а, получилось, вроде, компактно:
from codecs import open
from re import split
from collections import OrderedDict
text = open("load", "r", "utf-8")
s = text.read()
words = split('[\d\W]+', s)
words.remove('')
d = {}
for w in words:
    if w in d:
        d[w] += 1
    else:
        d[w] = 1
ALPHABET = {i[1]: i[0] for i in enumerate(u"абвгдеёжзийклмнопрстуфхцчшщъыьэюя")}
od = OrderedDict(sorted(d.items(), key=lambda x: ALPHABET[x[0][0].lower()]))
for i in od.items():
    print(i)
но сортирует всё-равно не корректно: только по первым буквам:
('емеля', 1)
('Ель', 1)
('ежевика', 3)
('ель', 2)
('ёжик', 2)
('ёлка', 3)
('Ёжик', 1)
('мороз', 1)
('метёлка', 1)
('метла', 1)
('муляж', 1)
('мёд', 1)
('улитка', 3)
как видно, вторые буквы уже плавают.
Мой вариант работает, но уж очень в нём много букофф:
from codecs import open
from functools import cmp_to_key
from re import split
from collections import OrderedDict
text = open("load", "r", "utf-8")
s = text.read()
words = split('[\d\W]+', s)
words.remove('')
d = {}
for w in words:
    if w in d:
        d[w] += 1
    else:
        d[w] = 1
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].lower() == y[j].lower():
            continue
        if x[j].lower() != 'ё' and y[j].lower() != 'ё':
            if x[j].lower() < y[j].lower():
                return -1
            else:
                return 1
        elif x[j].lower() == 'ё':
            if y[j].lower() > 'е':
                return -1
            else:
                return 1
        elif y[j].lower() == 'ё':
            if x[j].lower() > 'е':
                return 1
            else:
                return -1
    if len(x) < len(y):
        return -1
    elif len(x) > len(y):
        return 1
    else:
        return 0
od = OrderedDict(sorted(d.items(), key=cmp_to_key(comparator)))
for i in od.items():
    print(i)
Хочу сказать, что это же на джаве можно написать раза в 3 короче.
Pawl
FishHook
Потратьте час времени на изучение этих четырех типов коллекций и станет гораздо проще.
Что-то мне подсказывает, что если в языке не предусмотрена возможность сортировки карт “искаропки”, то, как ни читай доку, она не появится. В итоге я сделал, что было надо, хоть и с большим количеством кода, но уменьшить его, похоже, не получится Тем не менее, спасибо всем откликнувшимся, кое-что из Ваших ответов я почерпнул!
Shaman
Pawl
Хорошо, а как мне это сделать? Нашел вариант:
Вам просто не нужно этого делать. Не нужен Вам отсортированный словарь. Совсем.
Pawl
но сортирует всё-равно не корректно: только по первым буквам:
Конечно! Вы же не понимаете что пишете.
Shaman
Pawl
Хочу сказать, что это же на джаве можно написать раза в 3 короче.
Это на любом языке будет копрокодом.
Pawl
Shaman
Конечно! Вы же не понимаете что пишете.
согласен, лямбды я в питоне не понимаю, поэтому и привел свой вариант, который понимаю. В надежде на конструктив.
FishHook
Рабочий вариант сортировки по всему слову предлагал py.user.next
Чем он вам не нравится?
This is a "lo-fi" version of our main content. To view the full version with more information, formatting and images, please click here.
Powered by DjangoBB