Найти - Пользователи
Полная версия: Задача по Python
Начало » Центр помощи » Задача по Python
1 2 3
Shev
Отсортируйте данный итератор таким образом, чтобы его элементы оказались в порядке убывания частоты их появления, то есть по количеству раз, которое они появляются в элементах. Если два элемента имеют одинаковую частоту, они должны оказаться в том же порядке, в котором стояли изначально в итераторе.
 def frequency_sort(items):
    return (sorted(items, key=lambda x: items.count(x))) [::-1]

Частично решил таким образом. Прошу подсказать, каким образом выполнить условие, указанное в последнем предложении задачи. Желательно не готовое решение, а подсказка, чтобы дойти самому.
py.user.next
Shev
Желательно не готовое решение, а подсказка, чтобы дойти самому.
.count() не надо использовать.
Да и решение твоё тоже неправильное. Видимо, ты не понял задачу и наконструировал себе в фантазиях другую задачу и стал её решать. А ведь решать надо задачу именно такую, которая поставлена, а не такую, которая удобнее выглядит. В программировании реальных программ такое происходит сплошь и рядом: тебе нужно что-то сделать и оно нифига не просто, а другие варианты не подходят или их вообще нет. Так что учись сразу решать именно те задачи, которые поставлены, а не подравнивать задачи под то, что ты умеешь делать лучше всего.

Например, в итераторе расположены числа какие-то. Вот надо сначала выдать одинаковые числа из этого итератора, которые встречаются чаще всех остальных чисел в этом итераторе. Затем надо выдать одинаковые числа из этого итератора, которые встречаются чуть реже, чем самые частые числа. И так продолжать, пока не дойдёшь до самых редких чисел.

Вот здесь .count() (очень затратная операция) не нужен. Здесь нужен один проход по итератору, в результате которого появляется словарь. Потом по этому словарю строишь новый итератор. И в новом итераторе будут все те же элементы, что и в исходном итераторе, только они будут идти в этом порядке, который указан в задаче.
Shev
py.user.next
Видимо, ты не понял задачу и наконструировал себе в фантазиях другую задачу и стал её решать
Непонятно, откуда взялся такой вывод? Разве то, что я написал не сортирует итератор по количеству включений или решается какая то другая задача? Я новичок в программировании, но читаю русский текст вполне сносно.
С тем, что решение не правильное, спорить не буду, ибо не знаю.
За ответ Вам огромное спасибо, попробую решить через словарь, результат (если осилю) выложу на Ваш суд.
py.user.next
Shev
Непонятно, откуда взялся такой вывод?
Это я перепутал. У тебя в задании написано так, будто итератор содержит элементы, внутри которых надо что-то искать.
Shev
то есть по количеству раз, которое они появляются в элементах
Появиться в элементе может что-то, когда он сам по себе контейнер - список, кортеж, множество. А итератор может содержать не только простые элементы, но и списки, и кортежи, и даже другие итераторы, которые могут содержать тоже что угодно.

Shev
Разве то, что я написал не сортирует итератор по количеству включений
Сортирует. Только вот функции sorted() всё равно на порядок элементов; она их переставляет как хочет, лишь бы в конце они стали отсортированы. Поэтому тебе придётся сортировать самому, чтобы порядок не нарушился. Да и получить надо итератор в итоге. Можно, конечно, съехать и сказать, что можно получить список и сделать из него итератор в любой момент, но если этот объект уже участвует в какой-то цепочке действий, то вполне вероятно, что от него ждут наличия интерфейса итератора. А у списка интерфейса итератора нет.

Так что первое - тебе нужно учесть, что речь идёт про итератор. Итератор можно прочитать только один раз. Дальше он закончится и всегда будет законченным.
  
>>> it = iter([1, 1, 1, 3, 3, 2, 2, 2])
>>> sorted(it)
[1, 1, 1, 2, 2, 2, 3, 3]
>>> sorted(it)
[]
>>> sorted(it)
[]
>>>
Вот подаётся список в твою функцию
  
>>> def frequency_sort(items):
...     return (sorted(items, key=lambda x: items.count(x))) [::-1]
... 
>>> frequency_sort([1, 1, 1, 3, 3, 2, 2, 2])
[2, 2, 2, 1, 1, 1, 3, 3]
>>>
А вот подаётся итератор в твою функцию
  
>>> def frequency_sort(items):
...     return (sorted(items, key=lambda x: items.count(x))) [::-1]
... 
>>> it = iter([1, 1, 1, 2, 2, 2, 3, 3])
>>> frequency_sort(it)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 2, in frequency_sort
  File "<stdin>", line 2, in <lambda>
AttributeError: 'list_iterator' object has no attribute 'count'
>>>
То есть ты уже не учёл, что список и итератор - это абсолютно разные понятия. А в задаче речь именно про итератор идёт.

Второе. При возврате нужно также сохранить условие, что объект был итератором и остался итератором после сортировки.
Вот пришёл итератор, а вернулся список
  
>>> def sort_iter(it):
...     return sorted(it)
... 
>>> it = iter([1, 1, 1, 3, 3, 2, 2, 2])
>>> out = sort_iter(it)
>>> out
[1, 1, 1, 2, 2, 2, 3, 3]
>>> next(out)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: 'list' object is not an iterator
>>>
А вот пришёл итератор и вернулся итератор
  
>>> def sort_iter(it):
...     return iter(sorted(it))
... 
>>> it = iter([1, 1, 1, 3, 3, 2, 2, 2])
>>> out = sort_iter(it)
>>> out
<list_iterator object at 0x7fdf6a2c1780>
>>> next(out)
1
>>> next(out)
1
>>> list(out)
[1, 2, 2, 2, 3, 3]
>>>
То есть функция next() может быть применена только к итератору. И где-то кто-то может её применять уже и ждать от тебя отсортированный итератор, а ты вернёшь ему список, который вызовет исключение и падение программы, когда функция next() попытается взять элемент из этого списка.

Тебе сказали отсортировать итератор - будь добр взять его, отсортировать его и вернуть в результате такой же итератор, с которым можно дальше работать как с итератором. Это идеал.

В реальных же задачах данные могут быть вообще на миллионы и миллиарды элементов (датчик температуры с улицы Сезам посылает значения текущей температуры вообще бесконечно). Ты не сможешь хранить такие списки ни в памяти, ни где-то даже в разрозненном виде. Поэтому используются итераторы, где в памяти хранится только один элемент, а после его взятия из итератора он стирается и на его место ставится следующий элемент.
xam1816
добавить reverse=True и будет по условию
 def frequency_sort2(items):
    return sorted(items, key=lambda x: items.count(x),reverse=True)

py.user.next
Здесь нужен один проход по итератору, в результате которого появляется словарь.
со словарем понятно, интересно вот это
py.user.next
Потом по этому словарю строишь новый итератор. И в новом итераторе будут все те же элементы, что и в исходном итераторе, только они будут идти в этом порядке, который указан в задаче.
я словарь также sorted() отсортировал, а как через итератор делать?
py.user.next
xam1816
я словарь также sorted() отсортировал
sorted() переставит элементы произвольно. А там нужно выбирать максимальный из словаря, переставлять в новый словарь (или кортеж пар), потом удалять его из словаря и дальше снова выбирать максимальный из словаря и перекидывать его в новый словарь (или кортеж пар). Когда второй словарь (или кортеж пар) будет готов полностью, можно сделать из него список всех элементов и потом этот список передать в iter() и вернуть получившийся объект, либо сделать генератор с помощью генераторного выражения, который тоже итератором является, и вернуть получившийся объект.

Так ты сохранишь порядок частот элементов, у которых частоты одинаковые. Если у тебя было
  
{2: 258, 3:8, 1: 258}
То у тебя после сортировки выведутся сначала двойки, а потом единицы, а не сначала единицы, а потом двойки. А вот функция sorted() может запросто оставить как двойки впереди, так и единицы впереди. Это зависит от положения Луны. Поэтому её и не надо применять для этой конкретной сортировки.
Shev
py.user.next
А там нужно выбирать максимальный из словаря
Почему максимальный? По количеству вхождений сортировка нужна. Словарь я соорудил примерно так:
 def frequency_sort(items):
    b = {}
    for i in range(len(items)):
        b[i] = items[i]    
    return b
Но как сортировать словарь по количеству вхождений найти не могу. Причем там могут быть не только цифры но и строки. Либо есть еще мысль при создании словаря в качестве значений использовать количество вхождений:
 def frequency_sort(items):
    b = {}
    for i in range(len(items)):
        b[items[i]] = items.count(items[i])
    return b
И потом как то пытаться распаковать.
xam1816
 def sort_entry_count(items):
    d = {}
    for i in items:
        if i in d:
            d[i] += 1
        else:
            d[i] = 1
    sorted_d = sorted(d, key=lambda k: d[k], reverse=True)
    return (i for i in sorted_d for _ in range(d[i]))
 #
seq = iter(['a', 'a', 'b', 'b', 'b', 'c', 'd', 'e', 'e', 'e', 'e', 'e', 'e'])
res = sort_entry_count(seq)
print(res)
for i in res:
    print(i, ' ', end='')
<generator object sort_entry_count.<locals>.<genexpr> at 0x0000022F55E39B60>
e e e e e e b b b a a c d
Process finished with exit code 0
py.user.next
Shev
Почему максимальный? По количеству вхождений сортировка нужна. Словарь я соорудил примерно так:
  
def frequency_sort(items):
    b = {}
    for i in range(len(items)):
        b[i] = items[i]    
    return b
Не, словарь вот xam1816 составил правильно.

Дальше его надо правильно отсортировать - то есть не использовать функцию sorted(), а вручную сортировать. Так как ты не можешь контролировать внутреннее устройство функции sorted(), то ты не можешь сказать ей “не переставляй местами элементы, если они одинаковые”. Она просто может на каком-то компьютере переставить их местами, а на каком-то компьютере не переставить. Это будет зависеть от версии интерпретатора, установленного на том компьютере. Код у тебя один, а запускаться он может на разных питонах, на разных компьютерах, у разных людей, в разные годы. И вот где-то будет питон с такой функцией sorted(), а где-то он будет с другой функцией sorted(). Выглядеть эти функции снаружи будут одинаково, а после сортировки в одном получившемся списке элементы будут стоять в одном порядке, а в другом получившемся списке элементы будут стоять в другом порядке.

Тут если мы почитаем внимательно, то функцию sorted() гарантируют стабильной. То есть гарантируют, что она не переставляет.

https://docs.python.org/3/library/functions.html#sorted
The built-in sorted() function is guaranteed to be stable. A sort is stable if it guarantees not to change the relative order of elements that compare equal — this is helpful for sorting in multiple passes (for example, sort by department, then by salary grade).

Добавили эту информацию в документацию только в 2014 году.
https://bugs.python.org/issue22237

Там же, если пройти дальше по истории, можно увидеть, что функция sorted() стабильна с версии Python 2.2. Но в документации информация о том, что функция гарантируется стабильной, появилась только в 2014 году.
commit 9b1e92f5a199acf20041372950b96e5896e1b634
Author: Ezio Melotti <ezio.melotti@gmail.com>
Date: Tue Oct 28 12:57:11 2014 +0100

#22237: document that sorted() is guaranteed to be stable. Initial patch by Martin Panter.
Может ли существовать версия питона, которая была выпущена кем-то до 28 October 2014, в которой функцию sorted() изменили так, что она стала нестабильной? Теоретически может быть. Вероятность мизерная. Твой код могут на ней запустить? Могут. Твой код на ней сработает и выдаст не тот порядок элементов. Вероятность этого всего ещё меньше.

Можно оставить sorted() и радоваться, что всё сделал. Но что будет, когда ты выучишь питон, понапишешь на нём программ, а потом выучишь следующий язык программирования и там тоже надо будет что-то сортировать с сохранением порядка, а аналогичная функция sort(), которая там будет, не будет стабильной, как в питоне? Таких языков дохера и больше. Функция sort() не обязана стабильной быть. Я тебе скажу, что будет. Вместо написания программы ты будешь сидеть и заполнять этот пробел в знаниях, впервые изучая возможность ручной сортировки. То есть надо будет дело делать, а ты будешь сидеть и изучать, а как же его делать. Короче, не напишешь ты программу, так как слишком много пробелов у тебя будет. Будешь маленьким мальчиком, который ждёт, когда ему на блюдечке с голубой каёмочкой принесут функцию sorted(), разжуют её для него, сделают стабильной и в ротик положат, чтобы он мог пожувать её. Ух ты! Какой молодец! Мы сегодня покакали! Достижение - уровня Эйнштейна! не меньше. То есть программистом ты не будешь, будешь вечно хуйню какую-то ждать, когда же там за тебя всё сделают. А программы будут делать другие люди - умные дяденьки с бородами и с такими вот толстыми стёклами в очках. Только и зарплату будут платить всю тоже им, а не тебе такому красивому в белой рубашечке и с причёской ёжиком, а ты у них на побегушках будешь только там бегать где-то, так как таких, как ты, мешок можно насобирать, только свистни, а таких, как они, - раз два и обчёлся, потому и зарплатой будут удерживать их в компании, а не тебя.

Так что то, что функция sorted() в питоне стабильная, - это просто везение какое-то, очередной плюсик питона и так далее. В других языках тебе так не повезёт. Так как программа у тебя учебная, значит ты учишься. А если ты учишься, учись тому, что является общим для всех языков (которые были вчера, есть сегодня и будут завтра). Тогда твои знания и навыки будут более применимы и ты сможешь и сделать то, и сделать это, и сделать пятое, и сделать десятое. Когда программу надо будет писать (а учишься ты для того, чтобы писать программы, а не для того, чтобы в пиджачке бегать по этажам), писать ты её сможешь, только обладая знаниями и навыками. А знания и навыки ты получаешь вот прямо сейчас. Потом на получение этих знаний и навыков времени не будет, потому что потом ты будешь получать следующие знания и навыки, а за ними потом следующие и так далее.
Shev
py.user.next
вот xam1816 составил правильно
Мой второй вариант выдает такой же словарь, неправильно потому что там count используется?
До такого решения я самостоятельно не додумался. Я думаю тут даже не знаний не хватает, а практики.
py.user.next
пиджачке бегать по этажам
Я староват для этого). Чтобы было понимание: мне много лет, с Python пытаюсь разобраться самостоятельно (книги, интернет)
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